#include "qHID_USB.h"
#include "ui_qHID_USB.h"
#include <stdio.h>

//@VARIABLE:模块版本号
QString aVersion_QStr       = "Bate-V2.3";                                                                                                                          //@VARIABLE:模块版本号
QString aReleaseTime_QStr   = "2022年9月20日";                                                                                                                       //@VARIABLE:发行时间

QSemaphore mSendQueue_QSemaphore;                                                                                                                                   //@VARIABLE:数据生成缓冲区信号量（预定资源数为2，也就是说最多存在两个未被读取的缓冲区，否则阻塞等待读取后再次生成）
QSemaphore mSendReportQueue_QSemaphore;                                                                                                                             //@VARIABLE:报告数据生成缓冲区信号量（预定资源数为2，也就是说最多存在两个未被读取的缓冲区，否则阻塞等待读取后再次生成）






qHIDUSB_ToolBar::qHIDUSB_ToolBar()
{
    this->setAutoFillBackground(true);                                                                                                                                  //@STUDY:运行工具栏重绘背景
    this->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);                                                                                                              //@STUDY:文字显示在图标下方
    //this->setStyleSheet("background-color:argb(0,0,0,10%)");                                                                                                          //@STUDY:实现背景透明
}







qHIDUSB_TabWidget::qHIDUSB_TabWidget()
{

}






//@FUNC:HID_USB类构造函数，用于初始化各种类全局变量
c_HID_USB::c_HID_USB(int xSendMsDelay_Int)
{
    //@VARIABLE:初始化变量
    this->aHidInfo_HIDAPIP = NULL;                                                                                                                                      //@Variable:初始化HID信息指针
    this->aDevInfoList_StringP = NULL;                                                                                                                                  //@Variable:初始化HID信息数组指针
    this->aDevTotal_Int = -1;                                                                                                                                           //@Variable:当前已经连接的usb设备数量
    this->aEffectiveDevPCS_Int = 0;                                                                                                                                     //@VARIABLE:PID/VID相同的设备的数量
    this->aSendMsDelay_Int = xSendMsDelay_Int;                                                                                                                          //@VARIABLE:HID API发送函数延迟变量
    {                                                                                                                                                                   //@Variable:初始化HID信息数组指针
    this->aHIDInfoHead_QStrP = new QString[10];
    this->aHIDInfoHead_QStrP[cDevInfoIndex_PID]            = "【PID】：";
    this->aHIDInfoHead_QStrP[cDevInfoIndex_VID]            = "【VID】：";
    this->aHIDInfoHead_QStrP[cDevInfoIndex_PATH]           = "【路径】：";
    this->aHIDInfoHead_QStrP[cDevInfoIndex_Manufacturer]   = "【制造厂商】：";
    this->aHIDInfoHead_QStrP[cDevInfoIndex_SN]             = "【序列号】：";
    this->aHIDInfoHead_QStrP[cDevInfoIndex_RN]             = "【版本号】：";
    this->aHIDInfoHead_QStrP[cDevInfoIndex_Product]        = "【设备名称】：";
    this->aHIDInfoHead_QStrP[cDevInfoIndex_Interface]      = "【接口】：";
    this->aHIDInfoHead_QStrP[cDevInfoIndex_Usage]          = "【Usage】：";
    this->aHIDInfoHead_QStrP[cDevInfoIndex_UsagePage]      = "【UsagePage】：";
    }
}
// @FUNC:用于扫描当前已经连接的USB设备的信息，并存入List_DevInfo指针中的函数；
void c_HID_USB::sHID_Scan()
{
        this->sDevInfoList_Delete_Init();
        this->sDevInfoList_New_Init();
        //@NOTE:初始化上次存储的设备信息及数量统计
        aOrderlyHIDInfo_QList_QStringList.clear();
        aEffectiveDevPCS_Int = 0;

        int DevNum_Int = 0;                                                                                                                                             //@NOTE:用于记录当前扫描到的设备数的变量
        hid_device_info *aHidInfo_HIDAPIP_Temp = NULL;
        stringstream DevInfoToStr_stream;

        //@NOTE:获取当前连接的所有HID设备信息
        aHidInfo_HIDAPIP_Temp = this->aHidInfo_HIDAPIP;

        //@NOTE:用于将String数组中的信息转换为QString存入QStringList时所需要的数据
        QString tStrToQStr_QStr;
        QStringList tDevInfoToOrderly_QStrList;
        while (aHidInfo_HIDAPIP_Temp)
        {
            tDevInfoToOrderly_QStrList.clear();                                                                                                                         //@NOTE:初始化上一个设备的所有信息
            aHidInfoArray_HIDAPI[DevNum_Int] = *aHidInfo_HIDAPIP_Temp;
            //@NOTE:PID
            DevInfoToStr_stream.clear();
            DevInfoToStr_stream.str("");
            DevInfoToStr_stream << hex << aHidInfo_HIDAPIP_Temp->product_id;
            DevInfoToStr_stream >> this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_PID];
            if(cDevInfoZerofillCount > this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_PID].length())
            {
                this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_PID].insert(0, cDevInfoZerofillCount - this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_PID].length(), '0');
            }
            //@NOTE:将完成转换的QString添加到QStringList中
            tStrToQStr_QStr = "0x" +  QString::fromLocal8Bit(this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_PID].data()).toUpper();
            tDevInfoToOrderly_QStrList << tStrToQStr_QStr;

            //@NOTE:VID
            DevInfoToStr_stream.clear();
            DevInfoToStr_stream.str("");
            DevInfoToStr_stream << hex << aHidInfo_HIDAPIP_Temp->vendor_id;
            DevInfoToStr_stream >> this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_VID];
            if(cDevInfoZerofillCount > this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_VID].length())
            {
                this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_VID].insert(0, cDevInfoZerofillCount - this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_VID].length(), '0');
            }
            //@NOTE:将完成转换的QString添加到QStringList中
            tStrToQStr_QStr = "0x" +  QString::fromLocal8Bit(this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_VID].data()).toUpper();
            tDevInfoToOrderly_QStrList << tStrToQStr_QStr;

            //@NOTE:PATH
            this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_PATH] = aHidInfo_HIDAPIP_Temp->path;
            //@NOTE:将完成转换的QString添加到QStringList中
            tStrToQStr_QStr = QString::fromLocal8Bit(this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_PATH].data());
            tDevInfoToOrderly_QStrList << tStrToQStr_QStr;

            //@NOTE:manufacturer
            DevInfoToStr_stream.clear();
            DevInfoToStr_stream.str("");
            //wStrTemp = aHidInfo_HIDAPIP_Temp->manufacturer_string;
            //DevInfoToStr_stream << string(wStrTemp.begin(),wStrTemp.end());
            DevInfoToStr_stream << aHidInfo_HIDAPIP_Temp->manufacturer_string;
            DevInfoToStr_stream >> this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_Manufacturer];
            //@NOTE:将完成转换的QString添加到QStringList中
            tStrToQStr_QStr =QString::fromWCharArray(aHidInfo_HIDAPIP_Temp->manufacturer_string);
            tDevInfoToOrderly_QStrList << tStrToQStr_QStr;

            //@NOTE:SN
            DevInfoToStr_stream.clear();
            DevInfoToStr_stream.str("");
            DevInfoToStr_stream << aHidInfo_HIDAPIP_Temp->serial_number;
            DevInfoToStr_stream >> this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_SN];
            //@NOTE:将完成转换的QString添加到QStringList中
            tStrToQStr_QStr =QString::fromWCharArray(aHidInfo_HIDAPIP_Temp->serial_number);
            tDevInfoToOrderly_QStrList << tStrToQStr_QStr;

            //@NOTE:RN
            DevInfoToStr_stream.clear();
            DevInfoToStr_stream.str("");
            DevInfoToStr_stream << aHidInfo_HIDAPIP_Temp->release_number;
            DevInfoToStr_stream >> this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_RN];
            if(4 > this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_RN].length())
            {
                this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_RN].insert(0,cDevInfoZerofillCount - this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_RN].length(),'0');
            }
            //@NOTE:将完成转换的QString添加到QStringList中
            tStrToQStr_QStr = QString::fromLocal8Bit(this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_RN].data());
            tDevInfoToOrderly_QStrList << tStrToQStr_QStr;

            //@NOTE:product_string
            DevInfoToStr_stream.clear();
            DevInfoToStr_stream.str("");
            DevInfoToStr_stream << aHidInfo_HIDAPIP_Temp->product_string;
            DevInfoToStr_stream >> this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_Product];
            //@NOTE:将完成转换的QString添加到QStringList中
            tStrToQStr_QStr =QString::fromWCharArray(aHidInfo_HIDAPIP_Temp->product_string);
            tDevInfoToOrderly_QStrList << tStrToQStr_QStr;

            //@NOTE:Interface
            DevInfoToStr_stream.clear();
            DevInfoToStr_stream.str("");
            DevInfoToStr_stream << dec << aHidInfo_HIDAPIP_Temp->interface_number;
            DevInfoToStr_stream >> this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_Interface];
            //@NOTE:将完成转换的QString添加到QStringList中
            tStrToQStr_QStr = QString::fromLocal8Bit(this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_Interface].data());
            tDevInfoToOrderly_QStrList << tStrToQStr_QStr;

            //@NOTE:usage
            DevInfoToStr_stream.clear();
            DevInfoToStr_stream.str("");
            DevInfoToStr_stream << dec << aHidInfo_HIDAPIP_Temp->usage;
            DevInfoToStr_stream >> this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_Usage];
            //@NOTE:将完成转换的QString添加到QStringList中
            tStrToQStr_QStr = QString::fromLocal8Bit(this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_Usage].data());
            tDevInfoToOrderly_QStrList << tStrToQStr_QStr;

            //@NOTE:usage_page
            DevInfoToStr_stream.clear();
            DevInfoToStr_stream.str("");
            DevInfoToStr_stream << dec << aHidInfo_HIDAPIP_Temp->usage_page;
            DevInfoToStr_stream >> this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_UsagePage];
            //@NOTE:将完成转换的QString添加到QStringList中
            tStrToQStr_QStr = QString::fromLocal8Bit(this->aDevInfoList_StringP[DevNum_Int][cDevInfoIndex_UsagePage].data());
            tDevInfoToOrderly_QStrList << tStrToQStr_QStr;

            DevNum_Int++;
            aHidInfo_HIDAPIP_Temp = aHidInfo_HIDAPIP_Temp->next;


            //@NOTE:将此次循环的设备信息与库中已有设备进行对比排序后放入设备信息容器中
            int tFilterCnt_Int;
            tFilterCnt_Int = -1;
            if(0 == aOrderlyHIDInfo_QList_QStringList.count())                                                                                                          //@NOTE:如果容器是空的那么直接放入第一个HID设备的信息QStringList
            {
                aEffectiveDevPCS_Int++;
                aOrderlyHIDInfo_QList_QStringList << tDevInfoToOrderly_QStrList;
            }
            else                                                                                                                                                        //@NOTE:从第二个设备开始进行遍历对比排序
            {
                for (int tScanfCnt_Int = 0; tScanfCnt_Int < aOrderlyHIDInfo_QList_QStringList.count(); ++tScanfCnt_Int)                                                 //@NOTE:便利已经存储的所有设备的PID和VID
                {
                    if(aOrderlyHIDInfo_QList_QStringList.at(tScanfCnt_Int).at(cDevInfoIndex_PID) == tDevInfoToOrderly_QStrList.at(cDevInfoIndex_PID)
                            && aOrderlyHIDInfo_QList_QStringList.at(tScanfCnt_Int).at(cDevInfoIndex_VID) == tDevInfoToOrderly_QStrList.at(cDevInfoIndex_VID))
                    {
                        //tFilterCnt_Int < tScanfCnt_Int ? tFilterCnt_Int = tScanfCnt_Int : tFilterCnt_Int = tFilterCnt_Int ;                                             //@NOTE:如果有相同的VID、PID那么则记录容器中存放的相同PID、VID的QStringList的位置，直到最后一次找到相同PIDVID设备的位置。
                        tFilterCnt_Int = tScanfCnt_Int;
                    }
                }
                if(tFilterCnt_Int != -1)
                {
                    aOrderlyHIDInfo_QList_QStringList.insert((tFilterCnt_Int + 1),tDevInfoToOrderly_QStrList);                                                          //@NOTE:如果位置记录变量已经不是初始值了的话则直接向位置记录器记录的后面一位插入QStringList数据
                }
                else
                {
                    aEffectiveDevPCS_Int++;
                    aOrderlyHIDInfo_QList_QStringList.append(tDevInfoToOrderly_QStrList);                                                                               //@NOTE:如果没有找到的话位置记录变量依旧为初始值，那么则直接添加至容器末尾
                }
            }
        }
}

/*//@FUNC:重新扫描设备时删除之前开辟出来的用于存储设备信息的空间
bool c_HID_USB::sOpenDevForPath(QString xPath_QStr)
{
    const char *tPath_CharP = xPath_QStr.toStdString().data();
    aOpenedDev_hid_device_Write = hid_open_path(tPath_CharP);
    if(aOpenedDev_hid_device_Write == nullptr)
    {
        return false;
    }
    else
        return true;
}*/
/*//@FUNC:关闭当前打开的设备
void c_HID_USB::sCloseCurrentDev()
{
    hid_close(aOpenedDev_hid_device_Write);
    aOpenedDev_hid_device_Write = nullptr;
}*/
/*//@FUNC:发送消息到当前设备
int c_HID_USB::sSendMSNToDev(QString xMSN_QStr, int xReportID_Int)
{
    Q_UNUSED(xReportID_Int)
    //xMSN_QStr = xReportID_Int + xMSN_QStr;
    int tLen_Int = xMSN_QStr.length();
    QByteArray tMSN_QByteArray = xMSN_QStr.toLocal8Bit();
    int tResult = hid_write(aOpenedDev_hid_device_Write, (unsigned char *)tMSN_QByteArray.data(), tLen_Int);
    //@NOTE:延迟发送函数  //@STUDY:参考https://blog.csdn.net/Viciower/article/details/122690475
    QTime tComeBackeTime_Int = QTime::currentTime().addMSecs(aSendMsDelay_Int);                                                                                     //@NOTE:发送函数的发送延迟！避免连续两次调用HID发送函数导致的程序假死！
    while(QTime::currentTime() < tComeBackeTime_Int)
    {
        //@WARN：完成发送后等待1ms，HIDAPI短时间内调用两次hid_write()会导致程序卡死，所以设置等待函数
        //@TODO:2022年5月12日——其实这个问题通过多线程是可以解决的，但是程序开发已经接近尾声了，完全没有再改的欲望所以就通过延时避免发送装车绕过问题把！
        //@NOTE:猜测延时参数和PC的性能有关，性能越差延时应该越大！但是延迟越大连续发送多条消息时定时器的偏移量也就越大例如同时两个通道定时100ms发送指令，延时参数为20ms时，如果两个通道发送撞车那么理论最大延迟可达120ms；
        //@STUDY:2022年5月17日 —— 感觉不出意外应该是找到问题了……应该是因为子线程和主线程同时调用HID设备结构体导致……
    }
    return tResult;
}*/

//@FUNC:用于扫描设备数量开辟数据储存数组的函数
int c_HID_USB::sHIDDevPCSCheck()
{
    hid_device_info *aHidInfo_HIDAPIP_Temp=NULL;
    int PCSCheck_Int = 0;
    this->aHidInfo_HIDAPIP = hid_enumerate(0,0);                                                                                                                        //@STUDY:VID,PID遍历HID设备
    aHidInfo_HIDAPIP_Temp = this->aHidInfo_HIDAPIP;
    while (aHidInfo_HIDAPIP_Temp)                                                                                                                                       //@NOTE:通过便利计算当前设备数量
    {
        PCSCheck_Int++;
        aHidInfo_HIDAPIP_Temp = aHidInfo_HIDAPIP_Temp->next;
    }
    return PCSCheck_Int;
}
//@FUNC:修改消息发送延迟的函数
void c_HID_USB::sSetSendMSNMsDelay(int xSendMsDelay_Int)
{
    if(xSendMsDelay_Int < 10)
        xSendMsDelay_Int = 15;
    aSendMsDelay_Int = xSendMsDelay_Int;
}
//@FUNC:使用NEW为用于保存HID设备信息的动态数组开辟空间的函数
void c_HID_USB::sDevInfoList_New_Init()
{
    this->aDevTotal_Int = this->sHIDDevPCSCheck();                                                                                                                      //@NOTE:获取当前HID设备数量
    this->aDevInfoList_StringP = new string *[this->aDevTotal_Int];                                                                                                     //@NOTE:根据HID设备数量为二维指针创建指针数组
    this->aHidInfoArray_HIDAPI = new hid_device_info[this->aDevTotal_Int]();                                                                                            //@NOTE:根据HID设备数量创建指定数量的HID设备信息结构体
    for (int i = 0; i < this->aDevTotal_Int;i++)
    {
        this->aDevInfoList_StringP[i] = new string[10];                                                                                                                 //@NOTE:为刚才创建的一维指针数组的每一个指针创建10个用于存放HID设备信息地址，这样就可以通过一维指针和二维指针来操作指定设备的指定信息了，不过导入了QList<QString>后这个玩意就没啥太大的用了
    }
}
//@FUNC:使用delect[]删除之前为用于保存HID设备信息的动态数组开辟的空间的函数
void c_HID_USB::sDevInfoList_Delete_Init()
{
    if(0>=this->aDevTotal_Int){return;}//@NOTE:入参检测
    for (int i = 0; i < this->aDevTotal_Int;i++)
    {
        delete[] this->aDevInfoList_StringP[i];
    }
    delete[] this->aHidInfoArray_HIDAPI;
    delete[] this->aDevInfoList_StringP;
    this->aDevInfoList_StringP = NULL;
    this->aHidInfoArray_HIDAPI = NULL;
    this->aDevTotal_Int = 0;
}







//@FUNC:读取线程构造函数
qHIDRXThread::qHIDRXThread(QString xDevPath_QStr, int xReceiveCycle_Int)
{
    aDevPath_QStr = xDevPath_QStr;                                                                                                                                  //@NOTE:用于循环监听的HID设备路径信息
    aReceiveCycle_Int = xReceiveCycle_Int;                                                                                                                          //@NOTE:消息接收频率设置
}
//@FUNC:消息接收停止函数
void qHIDRXThread::sReadStop()
{
    aReadStart_Bool = false;
}
//@VARIABLE:用于控制接收线程接收扫描频率的变量
void qHIDRXThread::sAdjustReceiveCycle(int xNewCycle_Int)
{
    if(xNewCycle_Int < 1) return;
    aReceiveCycle_Int = xNewCycle_Int;
}
//@FUNC:多线程消息读取函数
void qHIDRXThread::run()
{
    unsigned char tRxBuff_Char[cSizeRXBuff];                                                                                                                        //@NOTE:用于存储从HID设备中收到的数据的缓冲区
    unsigned char *tBuffPoint_CharP;
    QString tRXBuff_QStr;
    aReadDev_hid_device = hid_open_path(aDevPath_QStr.toLatin1().data());                                                                                        //@STUDY:在子线程中创建用于读取消息的HID设备对象
    while(aReadStart_Bool)
    {
        //@NOTE:Buff完成接收后进行初始化
        for(int tBuffIndex_Int = 0; tBuffIndex_Int < cSizeRXBuff; ++tBuffIndex_Int)
        {
            tRxBuff_Char[tBuffIndex_Int] = '\0';
        }
        tBuffPoint_CharP = &tRxBuff_Char[0];                                                                                                                        //@NOTE:HidApi的读取函数形参设置的是char*所以需要将缓冲区数组的首位地址给指针传入读取函数
        hid_read(aReadDev_hid_device, tBuffPoint_CharP, cSizeRXBuff);                                                                                               //@STUDY:数据读取
        tRXBuff_QStr = QString((char*)(tBuffPoint_CharP));
        if(!tRXBuff_QStr.isEmpty())
            emit sGetMSN_Signal(tRXBuff_QStr);                                                                                                                      //@NOTE:将读取到的信息转发到主进程
        QThread::msleep(aReceiveCycle_Int);
    }
    hid_close(aReadDev_hid_device);
    aReadDev_hid_device = nullptr;
}





//@FUNC:发送线程构造函数
qHIDTXThread::qHIDTXThread(QString xDevPath_QStr)
{
    aDevPath_QStr = xDevPath_QStr;
}
//@FUNC:消息发送停止函数
void qHIDTXThread::sWriteStop()
{
    aWriteStart_Bool = false;
    aWriteOver_Bool = false;
}
//@FUNC:消息发送函数
bool qHIDTXThread::sMSNSend(QString xSendMSN_QStr, int xMSNModel_Int)
{
    if(aWriteOver_Bool)
    {
        aWriteOver_Bool = false;                                                                                                                                    //@NOTE:对发送数据的接收行为上锁但不阻塞，即不接收发送数据，直到完成消息发送后该标志位才会被发送函数置为TRUE
        aInputCnt_Int = xSendMSN_QStr.length();
        if(xMSNModel_Int == cASCIIModel)
            aSendMSN_QByteArray = xSendMSN_QStr.toLatin1();
        else
        {
            int tByteCnt_Int = aInputCnt_Int;
            QStringList tByteSplit_QStrList;
            for(int tByteIndex_Int = 0; tByteIndex_Int < tByteCnt_Int / 2; tByteIndex_Int++)
            {
                tByteSplit_QStrList << (xSendMSN_QStr.mid(tByteIndex_Int*2,2));
            }
            foreach (QString tByte_QStr, tByteSplit_QStrList) {
                //@STUDY:else中是int转char转16进制
                /*if((tByte_QStr.mid(0,1) >= 'A' && tByte_QStr.mid(0,1) <= 'F')
                        || (tByte_QStr.mid(0,1) >= 'a' && tByte_QStr.mid(0,1) <= 'f')
                        || (tByte_QStr.mid(1,1) >= 'A' && tByte_QStr.mid(1,1) <= 'F')
                        || (tByte_QStr.mid(1,1) >= 'a' && tByte_QStr.mid(1,1) <= 'f'))
                {
                    aSendMSN_QByteArray.append(QByteArray::fromHex(tByte_QStr.toLatin1()));
                }
                else
                {
                    char tMSNByte_Char = (char)(tByte_QStr.toInt()/10*16 + tByte_QStr.toInt()%10);
                    aSendMSN_QByteArray.append(tMSNByte_Char);
                }*/
                aSendMSN_QByteArray.append(QByteArray::fromHex(tByte_QStr.toLatin1()));
            }
        }
        mSendQueue_QSemaphore.release(1);                                                                                                                           //@NOTE:解锁发送函数，让其读取准备发送的消息并发送，发送后如果没有新的数据则阻塞等待！
        return true;
    }
    return false;
}
//@FUNC:多线程消息发送函数
void qHIDTXThread::run()
{
    //@NOTE:打开一个用于发送的HID设备
    //const char *tPath_CharP = aDevPath_QStr.toStdString().data();                                                                                                 //@NOTE:使用toStdString()在windows中运行正常，但是在windows7中会出现打开失败的现象，故替换为toLatin1()
    const char *tPath_CharP = aDevPath_QStr.toLatin1().data();
    aWriteDev_hid_device = hid_open_path(tPath_CharP);
    if(aWriteDev_hid_device == nullptr)                                                                                                                             //@NOTE:如果打开设备失败则返回false且不进入发送循环
    {
        aWriteStart_Bool = false;
        aOpenedResult_Int = cOpenFail;
    }
    else
    {
        aOpenedResult_Int = cOpenOK;
    }

    //@NOTE:初始化时默认阻塞，等待到有要发送的消息时释放
    if(int tFreeQueue_Int = mSendQueue_QSemaphore.available() > 0)                                                                                                  //@NOTE:确保上次线程结束时如果没来得及释放的信号量导致信号量资源不够，则再次释放信号量确保有一个个空闲信号量
    {
        mSendQueue_QSemaphore.acquire(tFreeQueue_Int);
    }

    while(aWriteStart_Bool)
    {
        mSendQueue_QSemaphore.acquire();                                                                                                                            //@NOTE:检查需要发送的数据是否准备就绪，没有则阻塞于此
        aResult_Int = hid_write(aWriteDev_hid_device, (unsigned char *)aSendMSN_QByteArray.data(), aInputCnt_Int);
        aSendMSN_QByteArray.clear();
        aWriteOver_Bool = true;
        emit sSendMSNResult_Signal(aResult_Int);                                                                                                                    //@NOTE:返回发送结果的信号，同时也是发送线程看门狗的饲料
    }
    //@NOTE:结束后关闭设备，并销毁指针
    if(aWriteDev_hid_device != nullptr)
    {
        hid_close(aWriteDev_hid_device);
        aWriteDev_hid_device = nullptr;
    }
}





//@FUNC:Report线程构造函数
qHIDSendReportThread::qHIDSendReportThread(QString xDevPath_QStr)
{
    aDevPath_QStr = xDevPath_QStr;
}
//@FUNC:消息发送停止函数
void qHIDSendReportThread::sWriteStop()
{
    aWriteStart_Bool = false;
    aWriteOver_Bool = false;
}
//@FUNC:报告发送函数
bool qHIDSendReportThread::sReportSend(QByteArray xSendMSN_QByteArray, int xReportModel_Int)
{
    if(aWriteOver_Bool)
    {
        aWriteOver_Bool = false;                                                                                                                                    //@NOTE:对发送数据的接收行为上锁但不阻塞，即不接收发送数据，直到完成消息发送后该标志位才会被发送函数置为TRUE
        aSendReport_QByteArray = xSendMSN_QByteArray;
        aReportModel_Int = xReportModel_Int;
        mSendReportQueue_QSemaphore.release(1);                                                                                                                     //@NOTE:解锁发送函数，让其读取准备发送的消息并发送，发送后如果没有新的数据则阻塞等待！
        return true;
    }
    return false;
}
//@FUNC:Report发送线程
void qHIDSendReportThread::run()
{
    //@NOTE:打开一个用于发送的HID设备
    const char *tPath_CharP = aDevPath_QStr.toLatin1().data();                                                                                                      //@NOTE:使用toStdString()在windows中运行正常，但是在windows7中会出现打开失败的现象，故替换为toLatin1()
    aWriteDev_hid_device = hid_open_path(tPath_CharP);
    if(aWriteDev_hid_device == nullptr)                                                                                                                             //@NOTE:如果打开设备失败则返回false且不进入发送循环
    {
        aWriteStart_Bool = false;
        aOpenedResult_Int = cOpenFail;
    }
    else
    {
        aOpenedResult_Int = cOpenOK;
    }

    //@NOTE:初始化时默认阻塞，等待到有要发送的消息时释放
    if(int tFreeQueue_Int = mSendReportQueue_QSemaphore.available() > 0)                                                                                            //@NOTE:确保上次线程结束时如果没来得及释放的信号量导致信号量资源不够，则再次释放信号量确保有一个个空闲信号量
    {
        mSendReportQueue_QSemaphore.acquire(tFreeQueue_Int);
    }

    while(aWriteStart_Bool)
    {
        mSendReportQueue_QSemaphore.acquire();                                                                                                                      //@NOTE:检查需要发送的数据是否准备就绪，没有则阻塞于此
        if(aReportModel_Int == cSetReport)
        {
            aResult_Int = hid_send_feature_report(aWriteDev_hid_device, (unsigned char *)aSendReport_QByteArray.data(), aSendReport_QByteArray.count());
            aWriteOver_Bool = true;
            emit sSendReportResult_Signal(aResult_Int);                                                                                                             //@NOTE:返回发送结果的信号，同时也是发送线程看门狗的饲料
        }
        else
        {
            aResult_Int = hid_get_feature_report(aWriteDev_hid_device, (unsigned char *)aSendReport_QByteArray.data(), aSendReport_QByteArray.count());
            aWriteOver_Bool = true;
            QString tRetureReport_QStr = "";
            unsigned char *tRetureReport_UCharP = (unsigned char *)aSendReport_QByteArray.data();
            for(int tReadCnt_Int = 0; tReadCnt_Int < (aResult_Int - 1); tReadCnt_Int++)
            {
                tRetureReport_QStr += QString::number(tRetureReport_UCharP[tReadCnt_Int],16) + " ";                                                                 //@STUDY:16进制数转为QString显示
            }
            if(!tRetureReport_QStr.isEmpty())
                emit  sGetReport_Signal(tRetureReport_QStr);
            emit sSendReportResult_Signal(aResult_Int);                                                                                                             //@NOTE:返回发送结果的信号，同时也是发送线程看门狗的饲料
        }
    }
    //@NOTE:结束后关闭设备，并销毁指针
    if(aWriteDev_hid_device != nullptr)
    {
        hid_close(aWriteDev_hid_device);
        aWriteDev_hid_device = nullptr;
    }
}





//@FUNC:重写关闭事件函数
void qHID_USB::closeEvent(QCloseEvent *event)
{
    sParamAutoSave();                                                                                                                                               //@NOTE:保存当前设置参数
    aCareDevDB_QSqlDatabase.close();                                                                                                                                //@NOTE:关闭数据库
    if(!aOpenDev_QPushButton->isEnabled())
    {
        sOn_CloseBtnClicked_Slot(true);
    }
    event->accept();
}
//@FUNC:创建子事件循环,在子事件循环中,父事件循环仍然是可以执行的,该方法不会阻塞线程
void qHID_USB::sUiDelayMsec(unsigned int xMsec_UNInt)
{
    //定义一个新的事件循环
    QEventLoop tLoop;
    //创建单次定时器,槽函数为事件循环的退出函数
    QTimer::singleShot(xMsec_UNInt, &tLoop, SLOT(quit()));
    //事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
    tLoop.exec();
}
qHID_USB::qHID_USB(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::qHID_USB)
{
    ui->setupUi(this);
    sSqlite_Init();
    UI_Init();
    sParam_Init();
    Signal_Init();
    aInitOver_Bool = true;
}

qHID_USB::~qHID_USB()
{
    delete ui;
}
//@FUNC:Ui初始化函数
void qHID_USB::UI_Init()
{
    //@NOTE:主界面设计
    //this->setMinimumWidth(1600);
    //this->setMinimumHeight(500);
    this->setWindowTitle(tr("PB-Box USB调试模块"));
    this->setWindowIcon(QIcon(":/images/images/USB.png"));


    //@NOTE:其他工具栏
    aToolBar_qHIDUSB_ToolBar = new qHIDUSB_ToolBar();
    aToolBar_qHIDUSB_ToolBar->setAllowedAreas(Qt::TopToolBarArea);
    aAutoClearDisplay_QWidget = new QWidget(this);
    QHBoxLayout *tAutoClearDisplay_QHBoxLayout = new QHBoxLayout();                                                                                                 //@VARIABLE:自动清空相关控件所在的QWidget
    QHBoxLayout *tDisplaySetting_QHBoxLayout = new QHBoxLayout();                                                                                                   //@VARIABLE:有关显示设置的组件布局
    QVBoxLayout *tDisplay_QVBoxLayout = new QVBoxLayout();
    aAutoClearTextCnt_QLabel = new QLabel(tr("自动清空触发进度"),this);
    aDisplayWithHex_QCheckBox = new QCheckBox(tr("显示消息为Hex"),this);
    aAutoClearTextCnt_QProgressBar = new QProgressBar(this);
    aAutoClearTextCnt_QProgressBar->setRange(0,100);                                                                                                                //@STUDY:关于QProgressBar更多用法参考：https://blog.csdn.net/qingzhuyuxian/article/details/107529352
    aAutoClearTextCnt_QProgressBar->setValue(0);
    tAutoClearDisplay_QHBoxLayout->addWidget(aAutoClearTextCnt_QLabel);
    tAutoClearDisplay_QHBoxLayout->addWidget(aAutoClearTextCnt_QProgressBar);
    tDisplaySetting_QHBoxLayout->addWidget(aDisplayWithHex_QCheckBox);
    tDisplay_QVBoxLayout->addLayout(tAutoClearDisplay_QHBoxLayout);
    tDisplay_QVBoxLayout->addLayout(tDisplaySetting_QHBoxLayout);
    aAutoClearDisplay_QWidget->setLayout(tDisplay_QVBoxLayout);
    QMenu *tAction_QMenu = new QMenu(this);
    tAction_QMenu->addAction(ui->action_MSNAddTime);
    tAction_QMenu->addAction(ui->action_MSNAddDate);
    tAction_QMenu->addSeparator();
    tAction_QMenu->addAction(ui->action_AutoEnter);
    tAction_QMenu->addAction(ui->action_AdjReturn);
    tAction_QMenu->addAction(ui->action_DisplaySend);
    tAction_QMenu->addAction(ui->action_CareWithOpen);
    ui->action_Setting->setMenu(tAction_QMenu);
    tAction_QMenu = new QMenu(this);
    tAction_QMenu->addAction(ui->action_ClearPath);
    ui->action_PathSelect->setMenu(tAction_QMenu);
    aToolBar_qHIDUSB_ToolBar->addAction(ui->action_PathSelect);
    aToolBar_qHIDUSB_ToolBar->addAction(ui->action_LogDir);
    aToolBar_qHIDUSB_ToolBar->addSeparator();
    aToolBar_qHIDUSB_ToolBar->addAction(ui->action_ClearTextBrow);
    aToolBar_qHIDUSB_ToolBar->addSeparator();
    ui->action_AppendDev->setEnabled(false);
    ui->action_DeleteDev->setEnabled(false);
    ui->action_SaveCared->setEnabled(false);
    ui->action_Uodo->setEnabled(false);
    aToolBar_qHIDUSB_ToolBar->addAction(ui->action_AppendDev);
    aToolBar_qHIDUSB_ToolBar->addAction(ui->action_DeleteDev);
    aToolBar_qHIDUSB_ToolBar->addAction(ui->action_SaveCared);
    aToolBar_qHIDUSB_ToolBar->addAction(ui->action_Uodo);
    aToolBar_qHIDUSB_ToolBar->addSeparator();
    aToolBar_qHIDUSB_ToolBar->addAction(ui->action_Setting);
    tAction_QMenu = new QMenu(this);
    tAction_QMenu->addAction(ui->action_AboutApp);
    tAction_QMenu->addAction(ui->action_QtVersion);
    tAction_QMenu->addAction(ui->action_Update);
    ui->action_About->setMenu(tAction_QMenu);
    aToolBar_qHIDUSB_ToolBar->addAction(ui->action_About);
    aToolBar_qHIDUSB_ToolBar->addSeparator();
    aToolBar_qHIDUSB_ToolBar->addWidget(aAutoClearDisplay_QWidget);
    ui->action_MSNAddDate->setChecked(true);
    ui->action_MSNAddTime->setChecked(true);
    aAutoClearTextCnt_QProgressBar->setRange(0,100);                                                                                                                //@STUDY:关于QProgressBar更多用法参考：https://blog.csdn.net/qingzhuyuxian/article/details/107529352
    aAutoClearTextCnt_QProgressBar->setValue(0);


    //@NOTE:初始化消息接收、设备扫描频率设置控件
    aCycleSet_QWidget = new QWidget(this);
    aReceiveCycle_QLabel = new QLabel(tr("消息接收间隔"),this);
    aAutoScanfCycle_QLabel = new QLabel(tr("设备扫描间隔"),this);
    aReceiveCycle_QSPinBox = new QSpinBox(this);
    aAutoScanfCycle_QSpinBox = new QSpinBox(this);
    aReceiveCycle_QSPinBox->setRange(1,60000);
    aAutoScanfCycle_QSpinBox->setRange(1,600000);
    aReceiveCycle_QSPinBox->setValue(1);
    aAutoScanfCycle_QSpinBox->setValue(5000);
    aReceiveCycle_QSPinBox->setSuffix("ms");
    aAutoScanfCycle_QSpinBox->setSuffix("ms");
    QVBoxLayout *tCycleLabel_QVBoxLayBox = new QVBoxLayout();
    QVBoxLayout *tCycleSpinBox_QVBoxLayBox = new QVBoxLayout();
    QHBoxLayout *tCycleSetWidget_QHBoxLayBox = new QHBoxLayout();
    tCycleLabel_QVBoxLayBox->addWidget(aReceiveCycle_QLabel);
    tCycleLabel_QVBoxLayBox->addWidget(aAutoScanfCycle_QLabel);
    tCycleSpinBox_QVBoxLayBox->addWidget(aReceiveCycle_QSPinBox);
    tCycleSpinBox_QVBoxLayBox->addWidget(aAutoScanfCycle_QSpinBox);
    tCycleSetWidget_QHBoxLayBox->addLayout(tCycleLabel_QVBoxLayBox);
    tCycleSetWidget_QHBoxLayBox->addLayout(tCycleSpinBox_QVBoxLayBox);
    aCycleSet_QWidget->setLayout(tCycleSetWidget_QHBoxLayBox);
    //@NOTE:初始化消息接收显示频率、HIDAPI发送函数调用强制间隔频率设置控件
    aCycleSet_QWidget = new QWidget(this);
    aRXMSNDisplayCycle_QLabel = new QLabel(tr("接收显示间隔"),this);
    aDevWriteCycle_QLabel = new QLabel(tr("消息发送间隔"),this);
    aRXMSNDisplayCycle_QSPinBox = new QSpinBox(this);
    aDevWriteCycle_QSpinBox = new QSpinBox(this);
    aDisplayMSN_QTimer = new QTimer(this);
    aRXMSNDisplayCycle_QSPinBox->setRange(1,60000);
    aDevWriteCycle_QSpinBox->setRange(0,50);
    aRXMSNDisplayCycle_QSPinBox->setValue(1);
    aDevWriteCycle_QSpinBox->setValue(15);
    aRXMSNDisplayCycle_QSPinBox->setSuffix("ms");
    aDevWriteCycle_QSpinBox->setSuffix("ms");
    QVBoxLayout *tCycleLabel2_QVBoxLayBox = new QVBoxLayout();
    QVBoxLayout *tCycleSpinBox2_QVBoxLayBox = new QVBoxLayout();
    tCycleLabel2_QVBoxLayBox->addWidget(aRXMSNDisplayCycle_QLabel);
    tCycleLabel2_QVBoxLayBox->addWidget(aDevWriteCycle_QLabel);
    tCycleSpinBox2_QVBoxLayBox->addWidget(aRXMSNDisplayCycle_QSPinBox);
    tCycleSpinBox2_QVBoxLayBox->addWidget(aDevWriteCycle_QSpinBox);
    tCycleSetWidget_QHBoxLayBox->addLayout(tCycleLabel2_QVBoxLayBox);
    tCycleSetWidget_QHBoxLayBox->addLayout(tCycleSpinBox2_QVBoxLayBox);
    aCycleSet_QWidget->setLayout(tCycleSetWidget_QHBoxLayBox);
    //aToolBar_qHIDUSB_ToolBar->addWidget(aCycleSet_QWidget);
    aToolBar_qHIDUSB_ToolBar->addSeparator();
    aDevWriteCycle_QLabel->setToolTip(tr("【警告】：在开发测试过程中发现，高频率调用HIDAPI库的发送函数会导致程序卡死在发送函数中。所以受限于HIDAPI库的发送函数的问题特别设立了该调节功能，该间隔时间与电脑性能成反比。如果测试过程中出现程序无响应的现象请适当将此值调大"));
    aDevWriteCycle_QSpinBox->setToolTip(tr("【警告】：在开发测试过程中发现，高频率调用HIDAPI库的发送函数会导致程序卡死在发送函数中。所以受限于HIDAPI库的发送函数的问题特别设立了该调节功能，该间隔时间与电脑性能成反比。如果测试过程中出现程序无响应的现象请适当将此值调大"));
    this->addToolBar(aToolBar_qHIDUSB_ToolBar);


    //@NOTE:设备操作工具栏及其相关控件设置
    aOperationBar_qHIDUSB_ToolBar = new qHIDUSB_ToolBar();
    aOperationBar_qHIDUSB_ToolBar->setAllowedAreas(Qt::TopToolBarArea);
    aDevOperation_QWidget = new QWidget();
    QHBoxLayout *tDevOperation_QHBoxLayout = new QHBoxLayout();
    aScanDev_QPushButton = new QPushButton("扫描设备");
    aCloseDev_QPushButton = new QPushButton(tr("关闭设备"));
    aOpenDev_QPushButton = new QPushButton("打开设备");
    aDevSelect_QComboBox = new QComboBox();
    aDevSelect_QComboBox->setMinimumWidth(500);
    aDevSelect_QComboBox->setMinimumHeight(30);
    QSizePolicy tSetting_QSizePolicy =  aDevSelect_QComboBox->sizePolicy();                                                                                         //@STUDY:设置控件拉伸策略
    tSetting_QSizePolicy.setHorizontalPolicy(QSizePolicy::Expanding);
    aDevSelect_QComboBox->setSizePolicy(tSetting_QSizePolicy);
    tDevOperation_QHBoxLayout->addWidget(aScanDev_QPushButton);
    tDevOperation_QHBoxLayout->addWidget(aCloseDev_QPushButton);
    tDevOperation_QHBoxLayout->addWidget(aOpenDev_QPushButton);
    tDevOperation_QHBoxLayout->addWidget(aDevSelect_QComboBox);
    aDevOperation_QWidget->setLayout(tDevOperation_QHBoxLayout);
    aOperationBar_qHIDUSB_ToolBar->addWidget(aDevOperation_QWidget);
    aOperationBar_qHIDUSB_ToolBar->addSeparator();
    aOperationBar_qHIDUSB_ToolBar->addWidget(aCycleSet_QWidget);
    this->addToolBarBreak(Qt::TopToolBarArea);
    this->addToolBar(aOperationBar_qHIDUSB_ToolBar);


    //@NOTE:用于装填Dock和Tab Widget的水平分割器
    aVSplitter_QSplitter = new QSplitter(this);                                                                                                                     //@NOTE:QSplitter初始化
    aVSplitter_QSplitter->setOrientation(Qt::Vertical);


    //@NOTE:将DockWidget相关控件设置
    aDockWidget_QWidget = new QWidget();
    QVBoxLayout *tDockWidget_QVBoxLayout = new QVBoxLayout();
    //aDevInfo_QDockWidget = new QDockWidget(this);                                                                                                                 //@NOTE:DockWidget初始化
    //aDevInfo_QDockWidget->setMinimumWidth(250);
    aDevList_QTreeView = new QTreeView();
    aDevList_QTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers);                                                                                         //@STUDY:设置为节点不可编辑
    aDevInfo_QStandardItemModel = new QStandardItemModel();
    aCurrentItem_QItemSelectionModel = new QItemSelectionModel(aDevInfo_QStandardItemModel);
    aDevList_QTreeView->setModel(aDevInfo_QStandardItemModel);
    aDevList_QTreeView->setSelectionModel(aCurrentItem_QItemSelectionModel);
    tDockWidget_QVBoxLayout->addWidget(aDevList_QTreeView);
    aDockWidget_QWidget->setLayout(tDockWidget_QVBoxLayout);
    //aDevInfo_QDockWidget->setWidget(aDockWidget_QWidget);
    aVSplitter_QSplitter->addWidget(aDockWidget_QWidget);


    //@NOTE:将TabWidget相关控件设置
    aTabWidget_qHIDUSB_TabWidget = new qHIDUSB_TabWidget();                                                                                                         //@NOTE:TabWidget初始化
    //aTabWidget_qHIDUSB_TabWidget->setMinimumWidth(1100);                                                                                                          //@WARN:此处如果限制宽度会导致程序在PB-Box中显示异常
    aDevInfoDisplay_QWidget = new QWidget();                                                                                                                        //@NOTE:当前设备信息显示页初始化
    QVBoxLayout *tDevInfoDisplay_QVBoxLayout = new QVBoxLayout();
    aDevInfoDisplay_QTextBrowser = new QTextBrowser();
    tDevInfoDisplay_QVBoxLayout->addWidget(aDevInfoDisplay_QTextBrowser);


    //@NOTE:消息发送页面
    aCommunication_QWidget = new QWidget(this);
    aSendModule_QWidget = new QWidget(this);
    aReportModule_QWidget = new QWidget(this);
    aMSNDisplay_QTextBrowser = new QTextBrowser(this);
    tSetting_QSizePolicy = aMSNDisplay_QTextBrowser->sizePolicy();
    tSetting_QSizePolicy.setHorizontalPolicy(QSizePolicy::Expanding);
    aMSNDisplay_QTextBrowser->setSizePolicy(tSetting_QSizePolicy);
    QVBoxLayout *tComWidget_QVBoxLayout = new QVBoxLayout();                                                                                                        //@VARIABLE:通信页面的垂直布局控件
    QVBoxLayout *tSendWidget_QVBoxLayout = new QVBoxLayout();                                                                                                       //@VARIABLE:用于存放发送控件的布局控件
    QVBoxLayout *tHexInput0_QVBoxLayout = new QVBoxLayout();                                                                                                        //@VARIABLE:用于存放16进制输入相关控件的布局
    QVBoxLayout *tHexInput1_QVBoxLayout = new QVBoxLayout();                                                                                                        //@VARIABLE:用于存放16进制输入相关控件的布局
    QVBoxLayout *tHexInput2_QVBoxLayout = new QVBoxLayout();                                                                                                        //@VARIABLE:用于存放16进制输入相关控件的布局
    QHBoxLayout *tMSN0_QHBoxLayout = new QHBoxLayout();                                                                                                             //@VARIABLE:消息发送0相关组件的布局控件
    QHBoxLayout *tMSN1_QHBoxLayout = new QHBoxLayout();                                                                                                             //@VARIABLE:消息发送1相关组件的布局控件
    QHBoxLayout *tMSN2_QHBoxLayout = new QHBoxLayout();                                                                                                             //@VARIABLE:消息发送2相关组件的布局控件
    QHBoxLayout *tSetReport_QHboxLayout = new QHBoxLayout();                                                                                                        //@VARIABLE:SetReport相关组件的布局控件
    aSendMSN0_QPushButton = new QPushButton(tr("发送"),this);
    aSendMSN1_QPushButton = new QPushButton(tr("发送"),this);
    aSendMSN2_QPushButton = new QPushButton(tr("发送"),this);
    aReportSend_QPushButton = new QPushButton("发送",this);
    aAutoSend0_QCheckBox = new QCheckBox(tr("定时发送"),this);
    aAutoSend1_QCheckBox = new QCheckBox(tr("定时发送"),this);
    aAutoSend2_QCheckBox = new QCheckBox(tr("定时发送"),this);
    aAutoSendReport_QCheckBox = new QCheckBox(tr("定时发送"),this);
    aHexModel0_QCheckBox = new QCheckBox(tr("16进制输入"),this);
    aHexModel1_QCheckBox = new QCheckBox(tr("16进制输入"),this);
    aHexModel2_QCheckBox = new QCheckBox(tr("16进制输入"),this);
    aAutoSend0_QSpinBox = new QSpinBox(this);
    aAutoSend1_QSpinBox = new QSpinBox(this);
    aAutoSend2_QSpinBox = new QSpinBox(this);
    aAutoSetReport_QSpinBox = new QSpinBox(this);
    aMSNEdit0_QPlainTextEdit = new QPlainTextEdit(this);
    aMSNEdit1_QPlainTextEdit = new QPlainTextEdit(this);
    aMSNEdit2_QPlainTextEdit = new QPlainTextEdit(this);
    aReportEdit_QLineEdit = new QLineEdit(this);
    aSetReportAutoAddSpace_QComboBox = new QComboBox(this);
    aSelectReportModel_QComboBox = new QComboBox(this);
    aHexInputModel0_QComboBox = new QComboBox(this);
    aHexInputModel1_QComboBox = new QComboBox(this);
    aHexInputModel2_QComboBox = new QComboBox(this);
    aAUTOSendMSN0_QTimer = new QTimer(this);
    aAUTOSendMSN1_QTimer = new QTimer(this);
    aAUTOSendMSN2_QTimer = new QTimer(this);
    aAUTOSetReport_QTimer = new QTimer(this);
    aAutoSend0_QSpinBox->setRange(100,600000);
    aAutoSend1_QSpinBox->setRange(100,600000);
    aAutoSend2_QSpinBox->setRange(100,600000);
    aAutoSetReport_QSpinBox->setRange(100,600000);
    aAutoSend0_QSpinBox->setValue(1000);
    aAutoSend1_QSpinBox->setValue(1000);
    aAutoSend2_QSpinBox->setValue(1000);
    aAutoSetReport_QSpinBox->setValue(1000);
    aAutoSend0_QSpinBox->setSuffix("ms");
    aAutoSend1_QSpinBox->setSuffix("ms");
    aAutoSend2_QSpinBox->setSuffix("ms");
    aAutoSetReport_QSpinBox->setSuffix("ms");
    //aMSNEdit0_QPlainTextEdit->setMinimumHeight(35);
    //aMSNEdit1_QPlainTextEdit->setMinimumHeight(35);
    //aMSNEdit2_QPlainTextEdit->setMinimumHeight(35);
    aMSNEdit0_QPlainTextEdit->setMaximumHeight(50);
    aMSNEdit1_QPlainTextEdit->setMaximumHeight(50);
    aMSNEdit2_QPlainTextEdit->setMaximumHeight(50);
#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
    QRegExp tInputFormatSetting_QRegExp("[0-9A-Fa-f ]{1,}");                                                                                                        //@VARIBALE:关于QRegExp类的详细用法参考：https://blog.csdn.net/qq_42482412/article/details/109476774?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_v31_ecpm-1-109476774-null-null.pc_agg_new_rank&utm_term=QRegexp%E8%BE%93%E5%85%A516%E8%BF%9B%E5%88%B6&spm=1000.2123.3001.4430
    QValidator *tInputSetting_QValidator = new QRegExpValidator(tInputFormatSetting_QRegExp,aReportEdit_QLineEdit);                                                 //@VARIABLE:将设置好的正则表达式规则套入至限制器中
#else
    QRegularExpression tInputFormatSetting_QRegularExpression("[0-9A-Fa-f ]{1,}");                                                                                  //@VARIBALE:Qt6中正则表达式相关类的类名有所变更
    QRegularExpressionValidator *tInputSetting_QValidator = new QRegularExpressionValidator(tInputFormatSetting_QRegularExpression,aReportEdit_QLineEdit);          //@VARIABLE:参考https://bbs.csdn.net/topics/607461078
#endif
    aReportEdit_QLineEdit->setValidator(tInputSetting_QValidator);                                                                                                  //@VARIABLE:将限制器套用到SetReport输入框中
    aReportEdit_QLineEdit->setPlaceholderText(tr("第一个八位为ReportID，后面请根据硬件规格自行添加数据，超出长度范围可能不支持，对于Set\\Get Report理解有限，所以请自行判断！"));     //@VARIABLE:输入提示
    QStringList tComboBoxSetting_QStrList = {"SetReport","GetReport"};
    aSelectReportModel_QComboBox->addItems(tComboBoxSetting_QStrList);
    tComboBoxSetting_QStrList.clear();
    tComboBoxSetting_QStrList << "关闭间隔" << "2字符间隔" << "4字符间隔";
    aSetReportAutoAddSpace_QComboBox->addItems(tComboBoxSetting_QStrList);
    aHexInputModel0_QComboBox->addItems(tComboBoxSetting_QStrList);
    aHexInputModel1_QComboBox->addItems(tComboBoxSetting_QStrList);
    aHexInputModel2_QComboBox->addItems(tComboBoxSetting_QStrList);
    tMSN0_QHBoxLayout->addWidget(aSendMSN0_QPushButton);
    tMSN0_QHBoxLayout->addWidget(aAutoSend0_QCheckBox);
    tMSN0_QHBoxLayout->addWidget(aAutoSend0_QSpinBox);
    tMSN0_QHBoxLayout->addWidget(aMSNEdit0_QPlainTextEdit);
    tHexInput0_QVBoxLayout->addWidget(aHexModel0_QCheckBox);
    tHexInput0_QVBoxLayout->addWidget(aHexInputModel0_QComboBox);
    tMSN0_QHBoxLayout->addLayout(tHexInput0_QVBoxLayout);
    tMSN1_QHBoxLayout->addWidget(aSendMSN1_QPushButton);
    tMSN1_QHBoxLayout->addWidget(aAutoSend1_QCheckBox);
    tMSN1_QHBoxLayout->addWidget(aAutoSend1_QSpinBox);
    tMSN1_QHBoxLayout->addWidget(aMSNEdit1_QPlainTextEdit);
    tHexInput1_QVBoxLayout->addWidget(aHexModel1_QCheckBox);
    tHexInput1_QVBoxLayout->addWidget(aHexInputModel1_QComboBox);
    tMSN1_QHBoxLayout->addLayout(tHexInput1_QVBoxLayout);
    tMSN2_QHBoxLayout->addWidget(aSendMSN2_QPushButton);
    tMSN2_QHBoxLayout->addWidget(aAutoSend2_QCheckBox);
    tMSN2_QHBoxLayout->addWidget(aAutoSend2_QSpinBox);
    tMSN2_QHBoxLayout->addWidget(aMSNEdit2_QPlainTextEdit);
    tHexInput2_QVBoxLayout->addWidget(aHexModel2_QCheckBox);
    tHexInput2_QVBoxLayout->addWidget(aHexInputModel2_QComboBox);
    tMSN2_QHBoxLayout->addLayout(tHexInput2_QVBoxLayout);
    tSetReport_QHboxLayout->addWidget(aReportSend_QPushButton);
    tSetReport_QHboxLayout->addWidget(aAutoSendReport_QCheckBox);
    tSetReport_QHboxLayout->addWidget(aAutoSetReport_QSpinBox);
    tSetReport_QHboxLayout->addWidget(aSelectReportModel_QComboBox);
    tSetReport_QHboxLayout->addWidget(aReportEdit_QLineEdit);
    tSetReport_QHboxLayout->addWidget(aSetReportAutoAddSpace_QComboBox);
    tSendWidget_QVBoxLayout->addLayout(tMSN0_QHBoxLayout);
    tSendWidget_QVBoxLayout->addLayout(tMSN1_QHBoxLayout);
    tSendWidget_QVBoxLayout->addLayout(tMSN2_QHBoxLayout);
    tSendWidget_QVBoxLayout->addLayout(tSetReport_QHboxLayout);
    aSendModule_QWidget->setLayout(tSendWidget_QVBoxLayout);
    //aSendModule_QWidget->setMaximumWidth(800);
    aSendModule_QWidget->setMaximumHeight(180);
    tComWidget_QVBoxLayout->addWidget(aSendModule_QWidget);
    tComWidget_QVBoxLayout->addWidget(aMSNDisplay_QTextBrowser);
    aCommunication_QWidget->setLayout(tComWidget_QVBoxLayout);
    aTabWidget_qHIDUSB_TabWidget->insertTab(0,
                                            aCommunication_QWidget,
                                            QIcon(":/images/images/chat1.png"),
                                            tr("【消息收发页】"));
    aVSplitter_QSplitter->addWidget(aTabWidget_qHIDUSB_TabWidget);
    this->setCentralWidget(aVSplitter_QSplitter);


    //@NOTE:设备选择页面
    aDevInfoDisplay_QWidget->setLayout(tDevInfoDisplay_QVBoxLayout);
    aTabWidget_qHIDUSB_TabWidget->insertTab(1,
                                            aDevInfoDisplay_QWidget,
                                            QIcon(":/images/images/Info.png"),
                                            tr("【设备选择页】"));


    //@NOTE:设备收藏、备注编辑页面
    QVBoxLayout *tDevEdit_QVBoxLayout = new QVBoxLayout();
    aDevEdit_QWidget = new QWidget();
    aDevEdit_QTableView = new QTableView();
    aDevEdit_QTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    aDevInfoTable_QStandardItemModel = new QStandardItemModel(this);
    aTableCurItem_QItemSelectionModel = new QItemSelectionModel(aDevInfoTable_QStandardItemModel);
    aDevEdit_QTableView->setModel(aDevInfoTable_QStandardItemModel);
    aDevEdit_QTableView->setSelectionModel(aTableCurItem_QItemSelectionModel);
    tDevEdit_QVBoxLayout->addWidget(aDevEdit_QTableView);
    aDevEdit_QWidget->setLayout(tDevEdit_QVBoxLayout);
    aTabWidget_qHIDUSB_TabWidget->insertTab(2,
                                            aDevEdit_QWidget,
                                            QIcon(":/images/images/cared (2).png"),
                                            tr("【设备收藏设置】"));


    //@NOTE:收藏的设备显示页
    QVBoxLayout *tDisplayCare_QVBoxLayout = new QVBoxLayout();
    aDisplayCare_QWidget = new QWidget();
    aDisplayCare_QTableView = new QTableView();
    aDisplayCare_QTableView->setModel(aCareDev_QSqlRelationalTableModel);
    aDisplayCare_QTableView->setSelectionModel(aCurCareDev_QItemSelectionModel);
    tDisplayCare_QVBoxLayout->addWidget(aDisplayCare_QTableView);
    aDisplayCare_QWidget->setLayout(tDisplayCare_QVBoxLayout);
    aTabWidget_qHIDUSB_TabWidget->insertTab(3,
                                            aDisplayCare_QWidget,
                                            QIcon(":/images/images/Cared.png"),
                                            tr("【收藏的设备】"));
    aDisplayCare_QTableView->setColumnWidth(0,500);                                                                                                                 //@STUDY:设置PID&VID&设备名列宽
    aDisplayCare_QTableView->setColumnWidth(1,835);                                                                                                                 //@STUDY:设置设备路径列宽
    aDisplayCare_QTableView->setColumnWidth(2,150);                                                                                                                 //@STUDY:设置制造厂商列宽
    aDisplayCare_QTableView->setColumnWidth(3,150);                                                                                                                 //@STUDY:设置序列号列宽


    //@NOTE:状态栏设备计数Label初始化
    aDisplayDevTotal_QLabel = new QLabel(tr("在线设备数："),this);
    aEffectiveDevTotal_QLabel = new QLabel(tr("有效设备数： "),this);
    aSendOkSize_QLabel = new QLabel(tr("已成功发送字节数： 0"),this);
    aSendNGSize_QLabel = new QLabel(tr("已发送失败次数： 0"),this);
    aAutoSavePath_QLabel = new QLabel((tr("数据自动保存路径：") + aAutoSavePath_QStr),this);
    aDisplayDevTotal_QLabel->setMinimumWidth(120);
    aEffectiveDevTotal_QLabel->setMinimumWidth(120);
    aSendOkSize_QLabel->setMinimumWidth(200);
    aSendNGSize_QLabel->setMinimumWidth(200);
    aAutoSavePath_QLabel->setMinimumWidth(500);
    ui->statusbar->addWidget(aDisplayDevTotal_QLabel);
    ui->statusbar->addWidget(aEffectiveDevTotal_QLabel);
    ui->statusbar->addWidget(aSendOkSize_QLabel);
    ui->statusbar->addWidget(aSendNGSize_QLabel);
    ui->statusbar->addWidget(aAutoSavePath_QLabel);


    //@NOTE:自动扫描定时器初始化
    aAUTOScanHIDDev_QTimer = new QTimer(this);


    //@NOTE:初始化通信按钮状态
    aOpenDev_QPushButton->setEnabled(true);
    aCloseDev_QPushButton->setEnabled(false);
    aScanDev_QPushButton->setEnabled(true);
    aDevSelect_QComboBox->setEnabled(true);
    aSendMSN0_QPushButton->setEnabled(false);
    aSendMSN1_QPushButton->setEnabled(false);
    aSendMSN2_QPushButton->setEnabled(false);
    aReportSend_QPushButton->setEnabled(false);
    aAutoSend0_QCheckBox->setEnabled(false);
    aAutoSend1_QCheckBox->setEnabled(false);
    aAutoSend2_QCheckBox->setEnabled(false);
    aAutoSendReport_QCheckBox->setEnabled(false);


    //@NOTE:初始化通信参数按钮
    ui->action_AutoEnter->setChecked(true);
    ui->action_AdjReturn->setChecked(true);
    ui->action_DisplaySend->setChecked(true);
    ui->action_CareWithOpen->setChecked(true);


    //@NOTE:初始化当前功能页以及设置设备详情的tabwidget的大小
    aTabWidget_qHIDUSB_TabWidget->setFixedHeight(200);
    aTabWidget_qHIDUSB_TabWidget->setCurrentIndex(cDevSelectTable);


    //@NOTE:HIDUSB数据接口对象初始化
    aHIDUSB_c_HID_USB = new c_HID_USB(aDevWriteCycle_QSpinBox->value());
    sHIDInfoUpdate_Slot();                                                                                                                                          //@NOTE:程序启动时默认进行一次扫描
    if(aAutoSavePath_QStr.isEmpty())                                                                                                                                //@NOTE:自动保存路径为空（首次使用软件的时候）
        on_action_ClearPath_triggered();
    aWriteThreadWatchDog_QTimer = new QTimer(this);
    aReportTXThreadWatchDog_QTimer = new QTimer(this);

    //@NOTE:Treeview初始化选择最左边
    QModelIndex tInitItem_QModelIndex = aDevInfo_QStandardItemModel->index(0,0);
    aCurrentItem_QItemSelectionModel->clearSelection();
    aCurrentItem_QItemSelectionModel->setCurrentIndex(tInitItem_QModelIndex,QItemSelectionModel::Columns);

}
//@FUNC:信号与槽初始化函数
void qHID_USB::Signal_Init()
{
    connect(this->aAUTOScanHIDDev_QTimer, &QTimer::timeout, this, &qHID_USB::sHIDInfoUpdate_Slot);                                                                  //@NOTE:用于定时扫描HID设备的信号
    connect(aDevSelect_QComboBox, SIGNAL(currentIndexChanged(int)),this, SLOT(sOn_CurrentDevChanged_Slot(int)));                                                    //@NOTE:根据当前所选设备更新显示当前设备的详细信息
    connect(aTabWidget_qHIDUSB_TabWidget, SIGNAL(currentChanged(int)), this, SLOT(sOn_TabWidgetChanged_Slot(int)));                                                 //@NOTE:当前所选TabWidget发生变化时用于改变界面的槽函数
    connect(aCurrentItem_QItemSelectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(sOn_TreeSelectChanged_Slot(QModelIndex,QModelIndex)));    //@NOTE:根据TreeView所选项修改ComboBox所选内容
    connect(aTableCurItem_QItemSelectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(sOn_DevEditCurChanged_Slot(QModelIndex,QModelIndex)));   //@NOTE:设备收藏设置页所选列发生变动

    connect(aOpenDev_QPushButton, SIGNAL(clicked(bool)), this, SLOT(sOn_OpenBtnClicked_Slot(bool)));                                                                //@NOTE:打开按钮被点击
    connect(aCloseDev_QPushButton, SIGNAL(clicked(bool)), this, SLOT(sOn_CloseBtnClicked_Slot(bool)));                                                              //@NOTE:关闭按钮被点击
    connect(aScanDev_QPushButton, SIGNAL(clicked(bool)), this , SLOT(sOn_ScanfBtnClicked_Slot(bool)));                                                              //@NOTE:设备扫描按钮被按下

    //@NOTE:消息发送相关
    connect(aSendMSN0_QPushButton, SIGNAL(clicked(bool)), this, SLOT(sOn_SendBtn0Clicked_Slot()));                                                                  //@NOTE:发送按钮0按下
    connect(aSendMSN1_QPushButton, SIGNAL(clicked(bool)), this, SLOT(sOn_SendBtn1Clicked_Slot()));                                                                  //@NOTE:发送按钮1按下
    connect(aSendMSN2_QPushButton, SIGNAL(clicked(bool)), this, SLOT(sOn_SendBtn2Clicked_Slot()));                                                                  //@NOTE:发送按钮2按下
    connect(aAUTOSendMSN0_QTimer, SIGNAL(timeout()), this, SLOT(sOn_SendBtn0Clicked_Slot()));                                                                       //@NOTE:自动发送定时器Timeout
    connect(aAUTOSendMSN1_QTimer, SIGNAL(timeout()), this, SLOT(sOn_SendBtn1Clicked_Slot()));                                                                       //@NOTE:自动发送定时器Timeout
    connect(aAUTOSendMSN2_QTimer, SIGNAL(timeout()), this, SLOT(sOn_SendBtn2Clicked_Slot()));                                                                       //@NOTE:自动发送定时器Timeout
    connect(aAutoSend0_QCheckBox, SIGNAL(clicked(bool)), this, SLOT(sOn_AutoSend0CheckedChanged_Slot(bool)));                                                       //@NOTE:自动发送按钮
    connect(aAutoSend1_QCheckBox, SIGNAL(clicked(bool)), this, SLOT(sOn_AutoSend1CheckedChanged_Slot(bool)));                                                       //@NOTE:自动发送按钮
    connect(aAutoSend2_QCheckBox, SIGNAL(clicked(bool)), this, SLOT(sOn_AutoSend2CheckedChanged_Slot(bool)));                                                       //@NOTE:自动发送按钮
    connect(aAutoSend0_QSpinBox, SIGNAL(valueChanged(int)), this, SLOT(sOn_TimerSpinBox0ValueChanged_Slot(int)));                                                   //@FUNC:定时器时间变化
    connect(aAutoSend1_QSpinBox, SIGNAL(valueChanged(int)), this, SLOT(sOn_TimerSpinBox1ValueChanged_Slot(int)));                                                   //@FUNC:定时器时间变化
    connect(aAutoSend2_QSpinBox, SIGNAL(valueChanged(int)), this, SLOT(sOn_TimerSpinBox2ValueChanged_Slot(int)));                                                   //@FUNC:定时器时间变化
    connect(aHexModel0_QCheckBox, SIGNAL(clicked(bool)), this, SLOT(sOn_OnHexInput0Clicked_Slot(bool)));                                                            //@FUNC:消息发送框0选择16进制输入
    connect(aHexModel1_QCheckBox, SIGNAL(clicked(bool)), this, SLOT(sOn_OnHexInput1Clicked_Slot(bool)));                                                            //@FUNC:消息发送框1选择16进制输入
    connect(aHexModel2_QCheckBox, SIGNAL(clicked(bool)), this, SLOT(sOn_OnHexInput2Clicked_Slot(bool)));                                                            //@FUNC:消息发送框2选择16进制输入
    connect(aHexInputModel0_QComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(sOn_OnHexModel0Changed_Slot()));                                                //@FUNC:当16进制自动空格模式变化时0
    connect(aHexInputModel1_QComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(sOn_OnHexModel1Changed_Slot()));                                                //@FUNC:当16进制自动空格模式变化时1
    connect(aHexInputModel2_QComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(sOn_OnHexModel2Changed_Slot()));                                                //@FUNC:当16进制自动空格模式变化时2

    //@NOTE:报告发送相关
    connect(aReportEdit_QLineEdit, SIGNAL(textEdited(QString)), this, SLOT(sOn_ReportEditInput_Slot(QString)));                                                     //@FUNC:当Report输入框0有输入时
    connect(aReportSend_QPushButton, SIGNAL(clicked(bool)), this, SLOT(sOn_SendReportBtnClicked_Slot()));                                                           //@NOTE:报告发送按钮0按下
    connect(aAUTOSetReport_QTimer, SIGNAL(timeout()), this, SLOT(sOn_SendReportBtnClicked_Slot()));                                                                 //@NOTE:自动发送定时器Timeout
    connect(aAutoSendReport_QCheckBox, SIGNAL(clicked(bool)), this, SLOT(sOn_AutoSendReportCheckedChanged_Slot(bool)));                                             //@NOTE:自动发送按钮
    connect(aAutoSetReport_QSpinBox, SIGNAL(valueChanged(int)), this, SLOT(sOn_SendReportSpinBoxValueChanged_Slot(int)));                                           //@FUNC:定时器时间变化
    connect(aSetReportAutoAddSpace_QComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(sOn_OnReportHexModelChanged_Slot(int)));                                 //@FUNC:Report16进制输入框空格模式变化

    connect(aAutoScanfCycle_QSpinBox, SIGNAL(valueChanged(int)), this, SLOT(sOn_AutoScanfCycleChaged_Slot(int)));                                                   //@NOTE:自动扫描频率发生变动
    connect(aReceiveCycle_QSPinBox, SIGNAL(valueChanged(int)), this, SLOT(sOn_ReceiveCycleChaged_Slot(int)));                                                       //@NOTE:自动接收频率发生变动
    connect(aDevWriteCycle_QSpinBox, SIGNAL(valueChanged(int)), this, SLOT(sOn_SendMSNMsDelayChaged_Slot(int)));                                                    //@NOTE:发送函数间隔延迟变动
    connect(aRXMSNDisplayCycle_QSPinBox, SIGNAL(valueChanged(int)), this, SLOT(sOn_RXTimerSpinBoxValueChanged_Slot(int)));                                          //@FUNC:接收计时器调节器数值变动
    connect(aDisplayMSN_QTimer, SIGNAL(timeout()), this, SLOT(sOn_RXTimerTimteout_Slot()));                                                                         //@FUNC:接收计时器超时

    connect(aWriteThreadWatchDog_QTimer, SIGNAL(timeout()), this, SLOT(sOn_WriteThreadWatchDogTimeout_Slot()));                                                     //@FUNC:发送子线程出现死锁！
    connect(aReportTXThreadWatchDog_QTimer, SIGNAL(timeout()), this, SLOT(sOn_WriteThreadWatchDogTimeout_Slot()));                                                  //@FUNC:报告发送子线程出现死锁
    connect(aMSNDisplay_QTextBrowser, SIGNAL(textChanged()), this, SLOT(sOn_TextBrowserTextChanged()));                                                             //@FUNC:消息显示框文本变化时触发，用于避免文本数量过多

    //@NOTE:定时设备扫描启动
    this->aAUTOScanHIDDev_QTimer->start(aAutoScanfCycle_QSpinBox->value());                                                                                         //@NOTE:每秒扫描一次HID设备

    //@NOTE:初始化16进制输入设置
    sOn_OnHexInput0Clicked_Slot(aHexModel0_QCheckBox->isChecked());
    sOn_OnHexInput1Clicked_Slot(aHexModel1_QCheckBox->isChecked());
    sOn_OnHexInput2Clicked_Slot(aHexModel2_QCheckBox->isChecked());
}
//@FUNC:设置参数初始化函数
void qHID_USB::sParam_Init()
{
    /*//@STUDY:QT数据类型与储存数据类型的互换，以及写入时的数据格式
     * 1.int -> qint16 -> 强转为(char*)写入
     * 2.QString -> .toLocal8Bit() -> QByteArray -> 无需强转直接写入
     * 3.float -> qreal -> 强转为(char*)写入
     * 4.bool无需变化数据类型 -> 强转为(char*)写入
    */
    //@NOTE:数据读取顺序，存储和读取必须使用相同的顺序
    /*//@NOTE:数据存储顺序
        QString类型
        0.参数保存文件所在路径（用于验证参数配置文件是否可用）
        1.日志保存路径；
        2.4个发送框的数据

        int类型
        3.4个自动发送定时器
        4.接收线程休眠时间
        5.自动扫描设备间隔
        6.接收消息显示间隔
        7.HIDAPI发送函数延迟
        8.Report发送模式
        9.4个16进制自动间隔字符数

        bool类型
        10.时间戳
        11.日期戳
        12.接收自动换行
        13.替换回车为\r\n
        14.显示发送消息
        15.自动收藏打开过的设备
        16.3个发送框16进制输入开关
        17.消息以16进制显示
    */

    QString tParamSavePath_QStr = QDir::currentPath() + "/Param/PB_Box-HIDUSB_Module-Param.dat";
    if(!sDirCheck("./Param/", "Param"))                                                                                                                             //@NOTE:检测参数保存文件夹是否存在
    {
        QMessageBox::warning(this,
                             tr("【警告】"),
                             tr("创建参数保存文件夹失败！本次程序所作的所有设置参数修改将不会被保存！"));
    }

    QFile tParamSaveFile_QFile(tParamSavePath_QStr);
    if(!tParamSaveFile_QFile.open(QIODevice::ReadWrite))                                                                                                            //@NOTE:尝试打开参数保存文件，如果不存在将自动创建
    {
        QMessageBox::warning(this,
                             tr("【警告】"),
                             tr("打开参数保存文件失败！本次程序所作的所有设置参数修改将不会被保存！"));
        return;
    }
    QDataStream tParamSaveFile_QDataStream(&tParamSaveFile_QFile);                                                                                                  //@NOTE:将数据读取流与打开的文件流绑定


    tParamSaveFile_QDataStream.setByteOrder(QDataStream::LittleEndian);                                                                                             //@STUDY:0.设置数据读取模式（大端还是小端字节序）


    //@NOTE:读取数据需要用到的变量
    //@VARIABLE:用于读取QString类型数据数据时所需要用到的变量
    uint tQStrLen_Uint;                                                                                                                                             //@VARIABLE:用于表示QString数据读取长度的空变量
    char *tQStrData_CharP = nullptr;                                                                                                                                //@VARIABLE:用于存储取出出来的QString数据的指针变量
    //@VARIABLE:用于读取int类型数据时所需用到的变量
    qint16 tIntData_Qint16;
    //@VARIABLE:用于读取bool类型数据时所需要用到的变量
    bool tBoolData_Bool;
    //@VARIABLE:用于对比读取数据的临时变量
    QString tQStrData_QStr;

    //@NOTE:检查专门用于文件准确性验证的参数文件存储地址是否与当前参数文件存储地址相同，如果不同则不读取数据文件
    tParamSaveFile_QDataStream.readBytes(tQStrData_CharP,tQStrLen_Uint);
    tQStrData_QStr = QString::fromLocal8Bit(tQStrData_CharP,tQStrLen_Uint);
    if(tQStrData_QStr.isEmpty())
        return;
    else
    {
        if(tQStrData_QStr != tParamSavePath_QStr)
        {
            QMessageBox::warning(this,
                                 tr("【警告】"),
                                 tr("参数保存文件数据异常！本次运行将采用默认参数！"));
            return;
        }
    }
    //@NOTE:日志数据保存路径读取
    tParamSaveFile_QDataStream.readBytes(tQStrData_CharP,tQStrLen_Uint);
    tQStrData_QStr = QString::fromLocal8Bit(tQStrData_CharP,tQStrLen_Uint);
    if(tQStrData_QStr.isEmpty()) return;
    aAutoSavePath_QStr = tQStrData_QStr;
    aAutoSavePath_QLabel->setText(tr("数据自动保存路径：") + aAutoSavePath_QStr);                                                                                      //@NOTE:更新状态栏路径显示
    //@NOTE:发送框0数据
    tParamSaveFile_QDataStream.readBytes(tQStrData_CharP,tQStrLen_Uint);
    aMSNEdit0_QPlainTextEdit->appendPlainText(QString::fromLocal8Bit(tQStrData_CharP,tQStrLen_Uint));
    //@NOTE:发送框1数据
    tParamSaveFile_QDataStream.readBytes(tQStrData_CharP,tQStrLen_Uint);
    aMSNEdit1_QPlainTextEdit->appendPlainText(QString::fromLocal8Bit(tQStrData_CharP,tQStrLen_Uint));
    //@NOTE:发送框2数据
    tParamSaveFile_QDataStream.readBytes(tQStrData_CharP,tQStrLen_Uint);
    aMSNEdit2_QPlainTextEdit->appendPlainText(QString::fromLocal8Bit(tQStrData_CharP,tQStrLen_Uint));
    //@NOTE:Report发送框数据
    tParamSaveFile_QDataStream.readBytes(tQStrData_CharP,tQStrLen_Uint);
    aReportEdit_QLineEdit->setText(QString::fromLocal8Bit(tQStrData_CharP,tQStrLen_Uint));


    //@NOTE:自动发送定时器0
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aAutoSend0_QSpinBox->setValue(tIntData_Qint16);
    //@NOTE:自动发送定时器1
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aAutoSend1_QSpinBox->setValue(tIntData_Qint16);
    //@NOTE:自动发送定时器2
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aAutoSend2_QSpinBox->setValue(tIntData_Qint16);
    //@NOTE:Report自动发送定时器
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aAutoSetReport_QSpinBox->setValue(tIntData_Qint16);
    //@NOTE:消息接收周期调整框
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aReceiveCycle_QSPinBox->setValue(tIntData_Qint16);
    //@NOTE:自动扫描设备频率设置
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aAutoScanfCycle_QSpinBox->setValue(tIntData_Qint16);
    //@NOTE:接收消息显示周期调整框
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aRXMSNDisplayCycle_QSPinBox->setValue(tIntData_Qint16);
    //@NOTE:HIDAPI发送函数调用强制间隔调整框
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aDevWriteCycle_QSpinBox->setValue(tIntData_Qint16);
    //@NOTE:Report发送模式
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aSelectReportModel_QComboBox->setCurrentIndex(tIntData_Qint16);
    //@NOTE:16进制自动间隔字符数
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aSetReportAutoAddSpace_QComboBox->setCurrentIndex(tIntData_Qint16);
    //@NOTE:MSN0-16进制自动间隔字符数
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aHexInputModel0_QComboBox->setCurrentIndex(tIntData_Qint16);
    //@NOTE:MSN1-16进制自动间隔字符数
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aHexInputModel1_QComboBox->setCurrentIndex(tIntData_Qint16);
    //@NOTE:MSN2-16进制自动间隔字符数
    tParamSaveFile_QDataStream.readRawData((char*)&tIntData_Qint16,sizeof(qint16));
    aHexInputModel2_QComboBox->setCurrentIndex(tIntData_Qint16);


    //@NOTE:是否显示时间戳
    tParamSaveFile_QDataStream.readRawData((char*)&tBoolData_Bool,sizeof(qint8));
    ui->action_MSNAddTime->setChecked(tBoolData_Bool);
    //@NOTE:是否显示日期戳
    tParamSaveFile_QDataStream.readRawData((char*)&tBoolData_Bool,sizeof(qint8));
    ui->action_MSNAddDate->setChecked(tBoolData_Bool);
    //@NOTE:是否启用接收自动换行
    tParamSaveFile_QDataStream.readRawData((char*)&tBoolData_Bool,sizeof(qint8));
    ui->action_AutoEnter->setChecked(tBoolData_Bool);
    //@NOTE:是否替换回车为\r\n
    tParamSaveFile_QDataStream.readRawData((char*)&tBoolData_Bool,sizeof(qint8));
    ui->action_AdjReturn->setChecked(tBoolData_Bool);
    //@NOTE:是否显示发送消息
    tParamSaveFile_QDataStream.readRawData((char*)&tBoolData_Bool,sizeof(qint8));
    ui->action_DisplaySend->setChecked(tBoolData_Bool);
    //@NOTE:自动收藏打开过的设备
    tParamSaveFile_QDataStream.readRawData((char*)&tBoolData_Bool,sizeof(qint8));
    ui->action_CareWithOpen->setChecked(tBoolData_Bool);
    //@NOTE:MSN0以16进制发送
    tParamSaveFile_QDataStream.readRawData((char*)&tBoolData_Bool,sizeof(qint8));
    aHexModel0_QCheckBox->setChecked(tBoolData_Bool);
    //@NOTE:MSN1以16进制发送
    tParamSaveFile_QDataStream.readRawData((char*)&tBoolData_Bool,sizeof(qint8));
    aHexModel1_QCheckBox->setChecked(tBoolData_Bool);
    //@NOTE:MSN2以16进制发送
    tParamSaveFile_QDataStream.readRawData((char*)&tBoolData_Bool,sizeof(qint8));
    aHexModel2_QCheckBox->setChecked(tBoolData_Bool);
    //@NOTE:消息以16进制显示
    tParamSaveFile_QDataStream.readRawData((char*)&tBoolData_Bool,sizeof(qint8));
    aDisplayWithHex_QCheckBox->setChecked(tBoolData_Bool);

    tParamSaveFile_QFile.close();
}
//@FUNC:数据库初始化函数(该函数参考LightMusicPlayer开源项目)
void qHID_USB::sSqlite_Init()
{
    if (QSqlDatabase::contains("qt_sql_default_connection"))                                                                                                        //@STUDY:增加这步是为了防止重复连接数据库
    {
        aCareDevDB_QSqlDatabase = QSqlDatabase::database("qt_sql_default_connection");
    }
    else
    {
        aCareDevDB_QSqlDatabase = QSqlDatabase::addDatabase("QSQLITE");
        aCareDevDB_QSqlDatabase.setDatabaseName("CareDevInfo.db");
        //aCareDevDB_QSqlDatabase.setUserName("Spectre");                                                                                                             //@QUESTION:数据库加密？//@GUESS:该设置可能会导致软件打开数据库时出现无法打开的现象故屏蔽
        //aCareDevDB_QSqlDatabase.setPassword("123456");
        if (!aCareDevDB_QSqlDatabase.open())                                                                                                                        //@NOTE:此处如果数据库不存在将会直接创建数据库
        {
            QMessageBox::critical(this,
                                  "【警告】",
                                  "无法打开数据库文件！错误信息如下所示：\n"
                                  + aCareDevDB_QSqlDatabase.lastError().databaseText());
            exit(-1);                                                                                                                                               //@QUESTION:数据库打开失败后直接自动关闭程序，不出意外应该是这里导致，但是也没有更好的的解决办法……
        }
    }

    //@NOTE:检查数据库中收藏设备表格是否存在，不存在则创建不存在的表
    QSqlQuery tQuery_QSqlQuery;
    tQuery_QSqlQuery.exec(QString("select count(*) from sqlite_master where type='table' and name='%1'").arg("CareDev"));
    if(tQuery_QSqlQuery.next())
    {
        if(tQuery_QSqlQuery.value(0).toInt()==0)                                                                                                                    //@NOTE:如果名字为CareDev的表没有找到，那么创建表
        {
            QSqlQuery tCreateQuery_QSqlQuery;
            //QString create_sql = "create table MusicInfo (id int primary key, name varchar(30), url varchar(200), author varchar(50), title varchar(50), duration bigint, albumTitle varchar(50), audioBitRate int)";
            tCreateQuery_QSqlQuery.prepare("create table CareDev (PID_VID_Product varchar(100), Path varchar(300), Manufacturer varchar(100), SN varchar(50), RN varchar(50), Interface varchar(20))");
            tCreateQuery_QSqlQuery.exec();
        }
    }


    //@NOTE:完成数据库检测/创建后连接至数据库数据模型
    aCareDev_QSqlRelationalTableModel = new QSqlRelationalTableModel(this,aCareDevDB_QSqlDatabase);
    aCurCareDev_QItemSelectionModel = new QItemSelectionModel(aCareDev_QSqlRelationalTableModel);
    aCareDev_QSqlRelationalTableModel->setTable("CareDev");                                                                                                         //@NOTE:将数据模型与数据库中的CareDev表绑定，完成绑定后将直接于数据模型中显示
    //aCareDev_QSqlRelationalTableModel->setEditStrategy(QSqlTableModel::OnFieldChange);                                                                              //@STUDY:设置数据库Table数据保存模式为“对模型的所有更改将立即应用到数据库”
    aCareDev_QSqlRelationalTableModel->setEditStrategy(QSqlTableModel::OnManualSubmit);                                                                             //@STUDY:设置数据库Table数据保存模式为“手动提交”
    aCareDev_QSqlRelationalTableModel->setSort(0,Qt::AscendingOrder);                                                                                               //@STUDY:以0列数据为基准进行升序排列

    //@NOTE:完成设置后打开数据库
    aCareDev_QSqlRelationalTableModel->select();                                                                                                                    //@NOTE:完成所有设置后打开数据库

    //@STUDY:连接SeletionModel与槽函数，用于更新选中数据时的状态
    connect(aCurCareDev_QItemSelectionModel,SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this,SLOT(sOn_CaredTableSelectionChanged_Slot(QModelIndex,QModelIndex)));
}
//@FUNC:TreeView以及DevEdit的表头和列宽初始化设置
void qHID_USB::sViewAndModel_Init()
{
    //@STUDY:初始化QTreeView和QTableView（DevEdit）的QStandardItemModel表头
    QStandardItem *tDevInfoHead_QStandardItem = nullptr;                                                                                                            //@STUDY:初始化QTreeView和QTableView的QStandardItemModel表头
    aDevInfoTable_QStandardItemModel->setHeaderData(0, Qt::Horizontal, "设备类型");
    aDevInfoTable_QStandardItemModel->setHeaderData(1, Qt::Horizontal, "收藏");
    tDevInfoHead_QStandardItem = new QStandardItem("PID & VID & 设备名称");
    aDevInfo_QStandardItemModel->setHorizontalHeaderItem(0, tDevInfoHead_QStandardItem);
    aDevInfoTable_QStandardItemModel->setHeaderData(2, Qt::Horizontal, "PID & VID & 设备名称");
    tDevInfoHead_QStandardItem = new QStandardItem("设备路径");
    aDevInfo_QStandardItemModel->setHorizontalHeaderItem(1, tDevInfoHead_QStandardItem);
    aDevInfoTable_QStandardItemModel->setHeaderData(3, Qt::Horizontal, "设备路径");
    tDevInfoHead_QStandardItem = new QStandardItem("制造厂商");
    aDevInfo_QStandardItemModel->setHorizontalHeaderItem(2, tDevInfoHead_QStandardItem);
    aDevInfoTable_QStandardItemModel->setHeaderData(4, Qt::Horizontal, "制造厂商");
    tDevInfoHead_QStandardItem = new QStandardItem("序列号");
    aDevInfo_QStandardItemModel->setHorizontalHeaderItem(3, tDevInfoHead_QStandardItem);
    aDevInfoTable_QStandardItemModel->setHeaderData(5, Qt::Horizontal, "序列号");
    tDevInfoHead_QStandardItem = new QStandardItem("版本号");
    aDevInfo_QStandardItemModel->setHorizontalHeaderItem(4, tDevInfoHead_QStandardItem);
    aDevInfoTable_QStandardItemModel->setHeaderData(6, Qt::Horizontal, "版本号");
    tDevInfoHead_QStandardItem = new QStandardItem("接口");
    aDevInfo_QStandardItemModel->setHorizontalHeaderItem(5, tDevInfoHead_QStandardItem);
    aDevInfoTable_QStandardItemModel->setHeaderData(7, Qt::Horizontal, "接口");
    tDevInfoHead_QStandardItem = new QStandardItem("Usage");
    aDevInfo_QStandardItemModel->setHorizontalHeaderItem(6, tDevInfoHead_QStandardItem);
    aDevInfoTable_QStandardItemModel->setHeaderData(8, Qt::Horizontal, "Usage");
    tDevInfoHead_QStandardItem = new QStandardItem("UsagePage");
    aDevInfo_QStandardItemModel->setHorizontalHeaderItem(7, tDevInfoHead_QStandardItem);
    aDevInfoTable_QStandardItemModel->setHeaderData(9, Qt::Horizontal, "UsagePage");
    tDevInfoHead_QStandardItem = nullptr;
    aDevList_QTreeView->setColumnWidth(0,500);                                                                                                                      //@STUDY:设置列宽
    aDevList_QTreeView->setColumnWidth(1,835);
    aDevList_QTreeView->setColumnWidth(2,150);
    aDevList_QTreeView->setColumnWidth(3,150);
    aDevEdit_QTableView->setColumnWidth(2,500);                                                                                                                     //@STUDY:设置列宽
    aDevEdit_QTableView->setColumnWidth(3,835);
    aDevEdit_QTableView->setColumnWidth(4,150);
    aDevEdit_QTableView->setColumnWidth(5,150);

    //@NOTE:设置SQLModel的中文表头
    aCareDev_QSqlRelationalTableModel->setHeaderData(0,Qt::Horizontal,"PID & VID & 设备名称");
    aCareDev_QSqlRelationalTableModel->setHeaderData(1,Qt::Horizontal,"设备路径");
    aCareDev_QSqlRelationalTableModel->setHeaderData(2,Qt::Horizontal,"制造厂商");
    aCareDev_QSqlRelationalTableModel->setHeaderData(3,Qt::Horizontal,"序列号");
    aCareDev_QSqlRelationalTableModel->setHeaderData(4,Qt::Horizontal,"版本号");
    aCareDev_QSqlRelationalTableModel->setHeaderData(5,Qt::Horizontal,"接口");

    sOn_CurrentDevChanged_Slot(0);                                                                                                                                  //@NOTE:初始化完成时默认显示第一个设备的信息
}
//@FUNC:用于查询传入路径信息的设备是否有被收藏
int qHID_USB::sQueryItemForSqlModel(QString xPath)
{
    QModelIndex tPathIndex_QModelIndex;
    for (int tSqlModelRow_Int = 0; tSqlModelRow_Int < aCareDev_QSqlRelationalTableModel->rowCount(); ++tSqlModelRow_Int)
    {
        tPathIndex_QModelIndex = aCareDev_QSqlRelationalTableModel->index(tSqlModelRow_Int, 1);                                                                     //@NOTE:2==PATH Item Column
        if(aCareDev_QSqlRelationalTableModel->data(tPathIndex_QModelIndex, Qt::EditRole).toString() == xPath)
        {
            return tSqlModelRow_Int;
        }
    }
    return -1;
}
//@FUNC:消息发送函数
void qHID_USB::sSendMSN(QString xMSN_QStr, int xSendBtnIndex_Int, int xReportID_Int, int xInputModel_Int)
{
    //@NOTE:检测是否需要添加日期时间戳
    sRefreshDateAndTime();
    QStringList tMSNList_QStrList;
    if(xMSN_QStr.indexOf("\n") < 0)
        tMSNList_QStrList << xMSN_QStr;
    else
        tMSNList_QStrList = xMSN_QStr.split("\n");
    foreach (QString tMSN_Auto, tMSNList_QStrList)                                                                                                                  //@NOTE:因为标准USB通信需要在指令前加数据报表，所以不能直接用Replace
    {
        if(tMSN_Auto != "")
        {
            if(ui->action_AdjReturn->isChecked())                                                                                                                   //@NOTE:是否需要把\n回车替换为\r\n
            {
                tMSN_Auto = QString::number(xReportID_Int,10) + tMSN_Auto + "\r\n";                                                                                 //@STUDY:tMSN_Auto = xReportID_Int + tMSN_Auto的写法在Qt6中将不再被支持，int类型不再支持隐式转换为QString，故请注意编写习惯
            }
            else
            {
                tMSN_Auto = QString::number(xReportID_Int,10) + tMSN_Auto + "\n";
            }
#if (cSendModel == cSplitMSN)
            if(xInputModel_Int == cASCIIModel)
                xMSN_QStr = tMSN_Auto;
#else
            xMSN_QStr += tMSN_Auto;
#endif

#if (cSendModel == cSplitMSN)
            bool tSendResult_Bool = aWriteThread_qHIDTXThread->sMSNSend(xMSN_QStr,xInputModel_Int);
            //sUiDelayMsec(aDevWriteCycle_QSpinBox->value());                                                                                                       //@STUDY:非阻塞延迟函数，参考：https://blog.csdn.net/hellokandy/article/details/106757349?utm_source=app&app_version=5.4.0&code=app_1562916241&uLinkId=usr1mkqgl919blen
            //@NOTE:延迟发送函数  //@STUDY:参考https://blog.csdn.net/Viciower/article/details/122690475
            QTime tComeBackeTime_Int = QTime::currentTime().addMSecs(aDevWriteCycle_QSpinBox->value());                                                             //@NOTE:发送函数的发送延迟！避免连续两次调用HID发送函数导致的程序假死！
            while(QTime::currentTime() < tComeBackeTime_Int)
            {
                //@WARN：完成发送后等待1ms，HIDAPI短时间内调用两次hid_write()会导致程序卡死，所以设置等待函数
                //@TODO:2022年5月12日——其实这个问题通过多线程是可以解决的，但是程序开发已经接近尾声了，完全没有再改的欲望所以就通过延时避免发送装车绕过问题把！
                //@NOTE:猜测延时参数和PC的性能有关，性能越差延时应该越大！但是延迟越大连续发送多条消息时定时器的偏移量也就越大例如同时两个通道定时100ms发送指令，延时参数为20ms时，如果两个通道发送撞车那么理论最大延迟可达120ms；
                //@STUDY:2022年5月17日 —— 感觉不出意外应该是找到问题了……应该是因为子线程和主线程同时调用HID设备结构体导致……
            }
            if(aSendFailCnt_Int < 10)
                aWriteThreadWatchDog_QTimer->start(1000);

            //int tSendSize_Int;
            if(tSendResult_Bool == true)
            {
                aSendFailCnt_Int = 0;
                //tSendSize_Int = xMSN_QStr.length();
                //@TODO:预留做字节数统计的区域

                xMSN_QStr = tr("【发送")
                            + QString::asprintf("%d】：",xSendBtnIndex_Int)
                            + xMSN_QStr;
                if(ui->action_DisplaySend->isChecked())                                                                                                                     //@NOTE:显示发送是否启用
                    aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + xMSN_QStr);
            }
            else
            {
                aSendFailCnt_Int++;
                aSendNGSize_Int += 1;
                aSendNGSize_QLabel->setText(tr("已发送失败次数： ") + QString::asprintf("%d",aSendNGSize_Int));
                //tSendSize_Int = sizeof(xMSN_QStr);
                xMSN_QStr = tr("【提示】：发送通道")
                            + QString::asprintf("%d发送[",xSendBtnIndex_Int)
                            + xMSN_QStr
                            + tr("] 失败！适当降低发送频率可以解决该问题！");
                aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + xMSN_QStr);
            }
            xMSN_QStr.replace("\r","\\r");
            xMSN_QStr.replace("\n","\\n");
            sDataAutoSave(aAutoSaveDateAndTime_QStr + xMSN_QStr);
            xMSN_QStr = "";
        }
#endif
    }
#if (cSendModel == cDefalutMSN)
    int tSendSize_Int = aHIDUSB_c_HID_USB->sSendMSNToDev(xMSN_QStr,xReportID_Int);
    if(tSendSize_Int != -1)
    {
        //@TODO:预留做字节数统计的区域
        aSendOkSize_Int += tSendSize_Int;
        xMSN_QStr = tr("【发送")
                    + QString::asprintf("%d】：",xSendBtnIndex_Int)
                    + xMSN_QStr;
        if(ui->action_DisplaySend->isChecked())                                                                                                                     //@NOTE:显示发送是否启用
            aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + xMSN_QStr);
        aSendOkSize_QLabel->setText(tr("已成功发送字节数： ") + QString::asprintf("%d",aSendOkSize_Int));
    }
    else
    {
        tSendSize_Int = sizeof(xMSN_QStr);
        aSendNGSize_Int += tSendSize_Int;
        xMSN_QStr = tr("【提示】：发送通道")
                    + QString::asprintf("%d发送[",xSendBtnIndex_Int)
                    + xMSN_QStr
                    + tr("] 失败！");
        aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + xMSN_QStr);
        aSendNGSize_QLabel->setText(tr("已发送失败字节数： ") + QString::asprintf("%d",aSendNGSize_Int));
        //sOn_CloseBtnClicked_Slot(true);                                                                                                                             //@NOTE:如果发送出错那么提示并关闭设备！
    }
    sDataAutoSave(aAutoSaveDateAndTime_QStr + xMSN_QStr);
#endif

}
//@FUNC:用于刷新日期时间戳的函数
void qHID_USB::sRefreshDateAndTime()
{
    aDateAndTimeInfo_QStr = "";
    aAutoSaveDateAndTime_QStr = "";
    aAutoSaveDateAndTime_QStr += QString::asprintf("【%d年%d月%d日】",QDate::currentDate().year(),QDate::currentDate().month(),QDate::currentDate().day());
    aAutoSaveDateAndTime_QStr += QString("【%1:%2:%3】").arg(QTime::currentTime().hour(), 2, 10, QLatin1Char('0')
                                                           ).arg(QTime::currentTime().minute(), 2, 10, QLatin1Char('0')
                                                                 ).arg(QTime::currentTime().second(), 2, 10, QLatin1Char('0'));                                     //@STUDY:补0貌似只能用.arg()实现，参考https://blog.csdn.net/libaineu2004/article/details/106931836
    if(ui->action_MSNAddDate->isChecked())
    {
        aDateAndTimeInfo_QStr += QDate::currentDate().toString("【yyyy年MM月dd日】");
    }
    if(ui->action_MSNAddTime->isChecked())
    {
        aDateAndTimeInfo_QStr += QTime::currentTime().toString("【HH:mm:ss】");                                                                                      //@STUDY:补0貌似只能用.arg()实现，参考https://blog.csdn.net/libaineu2004/article/details/106931836
    }
    aDateAndTimeInfo_QStr.replace("】【","-");
    aAutoSaveDateAndTime_QStr.replace("】【","-");
}
//@FUNC:在打开设备的同时开启自动保存功能
void qHID_USB::sStartSaveWithOpenDev()
{
    if(aAutoSavePath_QStr.isEmpty())                                                                                                                                //@NOTE:如果没有指定保存路径那么则储存于默认路径
    {
        on_action_ClearPath_triggered();
    }

    if(!QDir(aAutoSavePath_QStr).exists())                                                                                                                          //@NOTE:检查自动保存路径是否存在
    {
        QMessageBox::warning(this,
                             tr("【警告】"),
                             tr("自动保存路径不存在！将使用默认路径进行保存！"));
        on_action_ClearPath_triggered();
    }

    aAutoSavePath_QLabel->setText(tr("数据自动保存路径：") + aAutoSavePath_QStr);                                                                                      //@NOTE:更新状态栏路径显示

    aDataAutoSave_QFile = new QFile(aAutoSavePath_QStr
                                    + QDate::currentDate().toString("【Log-HIDUSB】yyyy年MM月dd日-")
                                    + QTime::currentTime().toString("HH时mm分ss秒")
                                    + ".txt");                                                                                                                      //@NOTE:创建数据保存文件
    if(!aDataAutoSave_QFile->open(QIODevice::ReadWrite))                                                                                                            //@NOTE:打开文件
    {
        QMessageBox::warning(this,
                             tr("【警告】"),
                             tr("日志文件打开失败！自动保存未启用！"));
        return;
    }

    sDataAutoSave(aDevInfoDisplay_QTextBrowser->document()->toPlainText()
                  + "\n【hid_write()调用延迟】："
                  + QString::number(aDevWriteCycle_QSpinBox->value())
                  +"ms\n\n");
    ui->action_ClearPath->setEnabled(false);
    ui->action_PathSelect->setEnabled(false);
}
//@FUNC:在关闭设备的同时关闭自动保存功能
void qHID_USB::sStopSaveWithCloseDev()
{
    if(aDataAutoSave_QFile != nullptr)
    {
        sDataAutoSave("\n");
        sDataAutoSave(aSendOkSize_QLabel->text());
        sDataAutoSave(aSendNGSize_QLabel->text());
        aDataAutoSave_QFile->close();
        aDataAutoSave_QFile = nullptr;                                                                                                                                  //@NOTE:关闭后初始化指针
        ui->action_ClearPath->setEnabled(true);
        ui->action_PathSelect->setEnabled(true);
    }
}
//@FUNC:读写数据自动保存函数
void qHID_USB::sDataAutoSave(QString xData_QStr)
{
    if(aDataAutoSave_QFile != nullptr)
    {
        QTextStream tSaveData_QStream(aDataAutoSave_QFile);
        if(xData_QStr.indexOf("\n") == -1)
        {
            xData_QStr += "\n";
        }
        emit sMSNAutoReport_Signal(xData_QStr);                                                                                                                     //@FUNC:用于转发调试信息到外部的信号

        tSaveData_QStream << xData_QStr.toUtf8();
    }
}
//@FUNC:程序参数自动保存函数
void qHID_USB::sParamAutoSave()
{
    /*//@STUDY:QT数据类型与储存数据类型的互换，以及写入时的数据格式
     * 1.int -> qint16 -> 强转为(char*)写入
     * 2.QString -> .toLocal8Bit() -> QByteArray -> 无需强转直接写入
     * 3.float -> qreal -> 强转为(char*)写入
     * 4.bool无需变化数据类型 -> 强转为(char*)写入
    */
    //@NOTE:数据读取顺序，存储和读取必须使用相同的顺序
    /*//@NOTE:数据存储顺序
        QString类型
        0.参数保存文件所在路径（用于验证参数配置文件是否可用）
        1.日志保存路径；
        2.4个发送框的数据

        int类型
        3.4个自动发送定时器
        4.接收线程休眠时间
        5.自动扫描设备间隔
        6.接收消息显示间隔
        7.HIDAPI发送函数延迟
        8.Report发送模式
        9.4个16进制自动间隔字符数

        bool类型
        10.时间戳
        11.日期戳
        12.接收自动换行
        13.替换回车为\r\n
        14.显示发送消息
        15.自动收藏打开过的设备
        16.3个发送框16进制输入开关
        17.消息以16进制显示
    */

    QString tParamSavePath_QStr = QDir::currentPath() + "/Param/PB_Box-HIDUSB_Module-Param.dat";
    if(!sDirCheck("./Param/", "Param"))                                                                                                                             //@NOTE:检测参数保存文件夹是否存在
    {
        QMessageBox::warning(this,
                             tr("【警告】"),
                             tr("创建参数保存文件夹失败！本次程序所作的所有设置参数修改将不会被保存！"));
    }

    QFile tParamSaveFile_QFile(tParamSavePath_QStr);
    if(!tParamSaveFile_QFile.open(QIODevice::WriteOnly | QIODevice::Truncate))                                                                                      //@NOTE:尝试以覆盖书写的方式打开参数保存文件，如果不存在将自动创建
    {
        QMessageBox::warning(this,
                             tr("【警告】"),
                             tr("打开参数保存文件失败！本次程序所作的所有设置参数修改将不会被保存！"));
        return;
    }
    QDataStream tParamSaveFile_QDataStream(&tParamSaveFile_QFile);                                                                                                  //@NOTE:将数据读写流与打开的文件流绑定


    tParamSaveFile_QDataStream.setByteOrder(QDataStream::LittleEndian);                                                                                             //@STUDY:0.设置数据写入模式（大端还是小端字节序）


    //@NOTE:写入数据需要用到的变量
    //@VARIABLE:用于写入int类型数据时所需用到的变量
    qint16 tIntData_Qint16;
    //@VARIABLE:用于写入bool类型数据时所需要用到的变量
    bool tBoolData_Bool;
    //@VARIABLE:用于写入QString类型数据时所需要用到的变量
    QByteArray tQStrData_QByteArray;


    //@NOTE:写入专门用于文件准确性验证的参数文件存储地址
    tQStrData_QByteArray = tParamSavePath_QStr.toLocal8Bit();
    tParamSaveFile_QDataStream.writeBytes(tQStrData_QByteArray,tQStrData_QByteArray.length());
    //@NOTE:日志数据保存路径写入
    tQStrData_QByteArray = aAutoSavePath_QStr.toLocal8Bit();
    tParamSaveFile_QDataStream.writeBytes(tQStrData_QByteArray,tQStrData_QByteArray.length());
    //@NOTE:发送框0数据
    tQStrData_QByteArray = aMSNEdit0_QPlainTextEdit->document()->toPlainText().toLocal8Bit();
    tParamSaveFile_QDataStream.writeBytes(tQStrData_QByteArray,tQStrData_QByteArray.length());
    //@NOTE:发送框1数据
    tQStrData_QByteArray = aMSNEdit1_QPlainTextEdit->document()->toPlainText().toLocal8Bit();
    tParamSaveFile_QDataStream.writeBytes(tQStrData_QByteArray,tQStrData_QByteArray.length());
    //@NOTE:发送框2数据
    tQStrData_QByteArray = aMSNEdit2_QPlainTextEdit->document()->toPlainText().toLocal8Bit();
    tParamSaveFile_QDataStream.writeBytes(tQStrData_QByteArray,tQStrData_QByteArray.length());
    //@NOTE:Report发送框数据
    tQStrData_QByteArray = aReportEdit_QLineEdit->text().toLocal8Bit();
    tParamSaveFile_QDataStream.writeBytes(tQStrData_QByteArray,tQStrData_QByteArray.length());


    //@NOTE:自动发送定时器0
    tIntData_Qint16 = aAutoSend0_QSpinBox->value();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));
    //@NOTE:自动发送定时器1
    tIntData_Qint16 = aAutoSend1_QSpinBox->value();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));
    //@NOTE:自动发送定时器2
    tIntData_Qint16 = aAutoSend2_QSpinBox->value();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));
    //@NOTE:Report自动发送定时器
    tIntData_Qint16 = aAutoSetReport_QSpinBox->value();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));
    //@NOTE:消息接收周期调整框
    tIntData_Qint16 = aReceiveCycle_QSPinBox->value();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));
    //@NOTE:自动扫描设备频率设置
    tIntData_Qint16 = aAutoScanfCycle_QSpinBox->value();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));
    //@NOTE:接收消息显示周期调整框
    tIntData_Qint16 = aRXMSNDisplayCycle_QSPinBox->value();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));
    //@NOTE:HIDAPI发送函数调用强制间隔调整框
    tIntData_Qint16 = aDevWriteCycle_QSpinBox->value();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));
    //@NOTE:Report发送模式
    tIntData_Qint16 = aSelectReportModel_QComboBox->currentIndex();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));
    //@NOTE:16进制自动间隔字符数
    tIntData_Qint16 = aSetReportAutoAddSpace_QComboBox->currentIndex();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));
    //@NOTE:MSN0-16进制自动间隔字符数
    tIntData_Qint16 = aHexInputModel0_QComboBox->currentIndex();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));
    //@NOTE:MSN1-16进制自动间隔字符数
    tIntData_Qint16 = aHexInputModel1_QComboBox->currentIndex();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));
    //@NOTE:MSN2-16进制自动间隔字符数
    tIntData_Qint16 = aHexInputModel2_QComboBox->currentIndex();
    tParamSaveFile_QDataStream.writeRawData((char*)&tIntData_Qint16,sizeof(qint16));


    //@NOTE:是否显示时间戳
    tBoolData_Bool = ui->action_MSNAddTime->isChecked();
    tParamSaveFile_QDataStream.writeRawData((char*)&tBoolData_Bool,sizeof(qint8));
    //@NOTE:是否显示日期戳
    tBoolData_Bool = ui->action_MSNAddDate->isChecked();
    tParamSaveFile_QDataStream.writeRawData((char*)&tBoolData_Bool,sizeof(qint8));
    //@NOTE:是否启用接收自动换行
    tBoolData_Bool = ui->action_AutoEnter->isChecked();
    tParamSaveFile_QDataStream.writeRawData((char*)&tBoolData_Bool,sizeof(qint8));
    //@NOTE:是否替换回车为\r\n
    tBoolData_Bool = ui->action_AdjReturn->isChecked();
    tParamSaveFile_QDataStream.writeRawData((char*)&tBoolData_Bool,sizeof(qint8));
    //@NOTE:是否显示发送消息
    tBoolData_Bool = ui->action_DisplaySend->isChecked();
    tParamSaveFile_QDataStream.writeRawData((char*)&tBoolData_Bool,sizeof(qint8));
    //@NOTE:自动收藏打开过的设备
    tBoolData_Bool = ui->action_CareWithOpen->isChecked();
    tParamSaveFile_QDataStream.writeRawData((char*)&tBoolData_Bool,sizeof(qint8));
    //@NOTE:MSN0以16进制发送
    tBoolData_Bool = aHexModel0_QCheckBox->isChecked();
    tParamSaveFile_QDataStream.writeRawData((char*)&tBoolData_Bool,sizeof(qint8));
    //@NOTE:MSN1以16进制发送
    tBoolData_Bool = aHexModel1_QCheckBox->isChecked();
    tParamSaveFile_QDataStream.writeRawData((char*)&tBoolData_Bool,sizeof(qint8));
    //@NOTE:MSN2以16进制发送
    tBoolData_Bool = aHexModel2_QCheckBox->isChecked();
    tParamSaveFile_QDataStream.writeRawData((char*)&tBoolData_Bool,sizeof(qint8));
    //@NOTE:消息以16进制显示
    tBoolData_Bool = aDisplayWithHex_QCheckBox->isChecked();
    tParamSaveFile_QDataStream.writeRawData((char*)&tBoolData_Bool,sizeof(qint8));

    tParamSaveFile_QFile.close();
}
//@FUNC:文件夹存在检测函数
bool qHID_USB::sDirCheck(QString xDirPath_QStr,  QString xDirName_QStr)
{
    QDir tCheckDir_QDir(xDirPath_QStr);
    xDirPath_QStr = tCheckDir_QDir.absolutePath() + "/";
    if(!tCheckDir_QDir.exists())
    {
        QDir tMkdirPath_QDir(xDirPath_QStr + "../");
        if(!tMkdirPath_QDir.mkdir(xDirName_QStr))
        {
            return false;
        }
    }
    return true;
}
//@FUNC:用于更新HID设备数量及信息的槽函数
void qHID_USB::sHIDInfoUpdate_Slot()
{
    //if(aOpenDev_QPushButton->isEnabled() || aDevCheck_Bool)
    //{
        //aDevCheck_Bool = false;
        if(aHIDUSB_c_HID_USB->aDevTotal_Int != aHIDUSB_c_HID_USB->sHIDDevPCSCheck()                                                                                     //@VARIABLE:设备数量变动
                || aScanfHIDDev_Bool)                                                                                                                                   //@VARIABLE:或者点击了手动扫描
        {                                                                                                                                                               //@VARIABLE:用于记录当前信息所属类型的计数器
            aScanfHIDDev_Bool = true;                                                                                                                                   //@WARN:扫描开始标志位，这个标志位非常重要！
            QString tCurOpendDevInfo_QStr = aDevSelect_QComboBox->currentText();                                                                                        //@NOTE:用于记录当前正被打开的设备的信息
            aDevSelect_QComboBox->clear();                                                                                                                              //@VARIABLE:扫描前清空各容器
            aDevInfoTable_QStandardItemModel->clear();
            aDevInfo_QStandardItemModel->clear();
            aChildCnt_QList_Int.clear();
            aCaredDev_QList_QStrList.clear();
            aGeneraldDev_QList_QStrList.clear();
            aTotalDev_QList_QStrList.clear();

            QString tDevInfo_QStr_Temp = "";

            aHIDUSB_c_HID_USB->sHID_Scan();                                                                                                                             //@NOTE:扫描当前已经连接的hid设备，并将信息更新到DevInfoList_Pointer中去
            aDisplayDevTotal_QLabel->setText(tr("在线设备数：")
                                             + QString::asprintf("%d",aHIDUSB_c_HID_USB->aDevTotal_Int));                                                               //@NOTE:更新设备总数到状态栏的Label中
            aEffectiveDevTotal_QLabel->setText(tr("有效设备数：")
                                               + QString::asprintf("%d",aHIDUSB_c_HID_USB->aEffectiveDevPCS_Int));                                                      //@NOTE:更新不同PIDVID设备的总数到状态栏的Label中


            //@NOTE:两个容器遍历无法合并，因为遍历时记录了相关序号，故合并会出现异常
            //@NOTE:用于拆分收藏设备和常规设备的循环遍历，同时将收藏设备优先显示至控件中
            QString tPIDAndVID_QStr = "";                                                                                                                               //@VARIABLE:用于记录前一个设备的PID/VID的临时变量
            QString tPIDAndVIDTemp_QStr = "";                                                                                                                           //@VARIABLE:用于记录当前设备的PID/VID的临时变量
            QStandardItem *tItemTemp_QStandardItem = nullptr;                                                                                                           //@VARIABLE:用于准备写入Model的数据的临时变量
            int tNewDevIndex_Int = -1;                                                                                                                                  //@VARIABLE:PID/VID不同的设备（父设备）数量计数器
            int tChildDevIndex_Int = -1;                                                                                                                                //@VARIABLE:PID/VID相同的设备（子设备）数量计数器
            int tTotalCnt_Int = 0;                                                                                                                                      //@VARIABLE:总设备计数器
            foreach(auto tDevInfoList_Auto, aHIDUSB_c_HID_USB->aOrderlyHIDInfo_QList_QStringList)
            {
                if(-1 != sQueryItemForSqlModel(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_PATH)))
                {

                    aCaredDev_QList_QStrList << tDevInfoList_Auto;
                    aTotalDev_QList_QStrList << tDevInfoList_Auto;

                    //@NOTE:准备写入ComboBox的数据
                    tDevInfo_QStr_Temp = aHIDUSB_c_HID_USB->aHIDInfoHead_QStrP[c_HID_USB::cDevInfoIndex_Product] + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Product) + " | "
                            + aHIDUSB_c_HID_USB->aHIDInfoHead_QStrP[c_HID_USB::cDevInfoIndex_PID] + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_PID) + " | "
                            + aHIDUSB_c_HID_USB->aHIDInfoHead_QStrP[c_HID_USB::cDevInfoIndex_VID] + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_VID) + " | "
                            + aHIDUSB_c_HID_USB->aHIDInfoHead_QStrP[c_HID_USB::cDevInfoIndex_Interface] + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Interface);
                    aDevSelect_QComboBox->addItem(QIcon(":/images/images/Cared.png"),tDevInfo_QStr_Temp);                                                               //@NOTE:将设备简要信息同步至用于设备选择的ComboBox

                    //@NOTE:此处为收藏设备循环遍历，所以全部勾
                    tItemTemp_QStandardItem = new QStandardItem("收藏的设备");
                    aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,0,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem();
                    tItemTemp_QStandardItem->setCheckState(Qt::Checked);
                    aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,1,tItemTemp_QStandardItem);
                    //@NOTE:准备将数据导入收藏设置表和QTreeView表中
                    tPIDAndVIDTemp_QStr = "⭐【 "
                            + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_PID)
                            + " | "
                            + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_VID)
                            + " 】："
                            + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Product);
                    tItemTemp_QStandardItem = new QStandardItem(tPIDAndVIDTemp_QStr);
                    aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,2,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_PATH));
                    aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,3,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Manufacturer));
                    aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,4,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_SN));
                    aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,5,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_RN));
                    aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,6,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Interface));
                    aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,7,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Usage));
                    aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,8,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_UsagePage));
                    aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,9,tItemTemp_QStandardItem);

                    //@NOTE:如果出现了新的PID、VID则表示当前VIDPID相同的设备已经完成录入，可以开始创建新的PIDVID父类选项卡
                    if(tPIDAndVID_QStr != tPIDAndVIDTemp_QStr)
                    {
                        tNewDevIndex_Int++;                                                                                                                                 //@NOTE:新设备计数器
                        if(tChildDevIndex_Int == -1)                                                                                                                        //@NOTE:首次进入不记录此数
                            tChildDevIndex_Int = 0;
                        else
                            aChildCnt_QList_Int << tChildDevIndex_Int;                                                                                                      //@NOTE:用于记录各个子节点数量的Int容器
                        tChildDevIndex_Int = 0;
                        tPIDAndVID_QStr = tPIDAndVIDTemp_QStr;
                        tItemTemp_QStandardItem = new QStandardItem(tPIDAndVID_QStr);
                        aDevInfo_QStandardItemModel->setItem(tNewDevIndex_Int,0,tItemTemp_QStandardItem);
                    }
                    //@NOTE:将数据放至QTreeView对应的表中
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_PATH));
                    aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,1,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Manufacturer));
                    aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,2,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_SN));
                    aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,3,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_RN));
                    aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,4,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Interface));
                    aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,5,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Usage));
                    aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,6,tItemTemp_QStandardItem);
                    tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_UsagePage));
                    aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,7,tItemTemp_QStandardItem);

                    tChildDevIndex_Int++;
                    tTotalCnt_Int++;
                }
                else
                {
                    aGeneraldDev_QList_QStrList << tDevInfoList_Auto;
                }
            }

            //@NOTE:将上方拆分之后的常规设备循环遍历，同时将常规设备优先显示至控件中
            tPIDAndVID_QStr = "";                                                                                                                                       //@VARIABLE:用于记录前一个设备的PID/VID的临时变量
            tPIDAndVIDTemp_QStr = "";                                                                                                                                   //@VARIABLE:用于记录当前设备的PID/VID的临时变量
            tItemTemp_QStandardItem = nullptr;                                                                                                                          //@VARIABLE:用于准备写入Model的数据的临时变量
            foreach (auto tDevInfoList_Auto, aGeneraldDev_QList_QStrList)
            {
                //@NOTE:准备写入ComboBox的数据
                aTotalDev_QList_QStrList << tDevInfoList_Auto;

                tDevInfo_QStr_Temp = aHIDUSB_c_HID_USB->aHIDInfoHead_QStrP[c_HID_USB::cDevInfoIndex_Product] + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Product) + " | "
                        + aHIDUSB_c_HID_USB->aHIDInfoHead_QStrP[c_HID_USB::cDevInfoIndex_PID] + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_PID) + " | "
                        + aHIDUSB_c_HID_USB->aHIDInfoHead_QStrP[c_HID_USB::cDevInfoIndex_VID] + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_VID) + " | "
                        + aHIDUSB_c_HID_USB->aHIDInfoHead_QStrP[c_HID_USB::cDevInfoIndex_Interface] + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Interface);

                aDevSelect_QComboBox->addItem(tDevInfo_QStr_Temp);                                                                                                      //@NOTE:将设备简要信息同步至用于设备选择的ComboBox


                //@NOTE:此处为未收藏设备循环遍历，所以全部去勾
                tItemTemp_QStandardItem = new QStandardItem("普通的设备");
                aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,0,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem();
                tItemTemp_QStandardItem->setCheckState(Qt::Unchecked);
                aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,1,tItemTemp_QStandardItem);
                //@NOTE:准备将数据导入收藏设置表和QTreeView表中
                tPIDAndVIDTemp_QStr = "【 "
                        + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_PID)
                        + " | "
                        + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_VID)
                        + " 】："
                        + tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Product);
                tItemTemp_QStandardItem = new QStandardItem(tPIDAndVIDTemp_QStr);
                aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,2,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_PATH));
                aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,3,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Manufacturer));
                aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,4,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_SN));
                aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,5,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_RN));
                aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,6,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Interface));
                aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,7,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Usage));
                aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,8,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_UsagePage));
                aDevInfoTable_QStandardItemModel->setItem(tTotalCnt_Int,9,tItemTemp_QStandardItem);



                //@NOTE:如果出现了新的PID、VID则表示当前VIDPID相同的设备已经完成录入，可以开始创建新的PIDVID父类选项卡
                if(tPIDAndVID_QStr != tPIDAndVIDTemp_QStr)
                {
                    tNewDevIndex_Int++;                                                                                                                                 //@NOTE:新设备计数器
                    if(tChildDevIndex_Int == -1)                                                                                                                        //@NOTE:首次进入不记录此数
                        tChildDevIndex_Int = 0;
                    else
                        aChildCnt_QList_Int << tChildDevIndex_Int;                                                                                                      //@NOTE:用于记录各个子节点数量的Int容器
                    tChildDevIndex_Int = 0;
                    tPIDAndVID_QStr = tPIDAndVIDTemp_QStr;
                    tItemTemp_QStandardItem = new QStandardItem(tPIDAndVID_QStr);
                    aDevInfo_QStandardItemModel->setItem(tNewDevIndex_Int,0,tItemTemp_QStandardItem);
                }
                //@NOTE:将数据放至QTreeView对应的表中
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_PATH));
                aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,1,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Manufacturer));
                aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,2,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_SN));
                aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,3,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_RN));
                aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,4,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Interface));
                aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,5,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_Usage));
                aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,6,tItemTemp_QStandardItem);
                tItemTemp_QStandardItem = new QStandardItem(tDevInfoList_Auto.at(c_HID_USB::cDevInfoIndex_UsagePage));
                aDevInfo_QStandardItemModel->item(tNewDevIndex_Int,0)->setChild(tChildDevIndex_Int,7,tItemTemp_QStandardItem);

                tChildDevIndex_Int++;
                tTotalCnt_Int++;
            }
            aChildCnt_QList_Int << tChildDevIndex_Int;                                                                                                                  //@NOTE:最后一次的子类数量也需要记录
            aScanfHIDDev_Bool = false;                                                                                                                                  //@WARN：该入参检测是必要的，否则程序将在重新扫描设备时响应槽函数，进而导致程序崩溃！！！
            sViewAndModel_Init();                                                                                                                                       //@NOTE:扫描结束后手动触发槽函数

            //@NOTE:扫描当前打开的设备是否还存在
            if(!aOpenDev_QPushButton->isEnabled())
            {
                bool tDevDisconnect_Bool = true;                                                                                                                        //@VARIABLE:设备断开连接标志位
                foreach (QStringList tDevInfoList_QStrList, aTotalDev_QList_QStrList)
                {
                    if(tDevInfoList_QStrList.at(c_HID_USB::cDevInfoIndex_PATH) == aOpenedDevPath_QStr)
                    {
                        tDevDisconnect_Bool = false;                                                                                                                    //@VARIABLE:设备没有断开连接
                    }
                }
                if(tDevDisconnect_Bool)
                {
                    //@NOTE:检测是否需要添加日期时间戳
                    sRefreshDateAndTime();
                    QString tTipMSN_QStr = tr("【警告】：检测到设备 ")
                            + tCurOpendDevInfo_QStr
                            + tr(" 已经断开连接！");
                    aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + tTipMSN_QStr);
                    sDataAutoSave(aAutoSaveDateAndTime_QStr + tTipMSN_QStr);
                    sOn_CloseBtnClicked_Slot(true);
                }
            }
        }
    //}
}
//@FUNC:当前所选设备发生变化时变更显示信息的槽函数
void qHID_USB::sOn_CurrentDevChanged_Slot(int xCurrentIndex_Int)
{
    if(aDevSelect_QComboBox->count() <= 0) return;
    if(aScanfHIDDev_Bool == true) return;                                                                                                                           //@WARN：该入参检测是必要的，否则程序将在重新扫描设备时响应槽函数，进而导致程序崩溃！！！

    //@NOTE:判断使用收藏列表还是常规列表
    QList<QStringList> tDev_QList_QStrList;
    int tListIndex_Int = 0;
    if(xCurrentIndex_Int < aCaredDev_QList_QStrList.count())
    {
        tDev_QList_QStrList = aCaredDev_QList_QStrList;
    }
    else
    {
        tListIndex_Int = xCurrentIndex_Int - aCaredDev_QList_QStrList.count();
        tDev_QList_QStrList = aGeneraldDev_QList_QStrList;
    }
    aDevInfoDisplay_QTextBrowser->clear();                                                                                                                          //@NOTE:设备变更则清空之前设备的信息
    int tInfoClassIndex_Int = 0;                                                                                                                                    //@NOTE:当前信息类型
    foreach (auto tDevInfo_Auto, tDev_QList_QStrList.at(tListIndex_Int))                                                                                            //@NOTE:遍历当前设备所有信息
    {
        if((tInfoClassIndex_Int == 0)
                || (tInfoClassIndex_Int == 1)
                || (tInfoClassIndex_Int == 2)
                || (tInfoClassIndex_Int == 7))
        /*if((tInfoClassIndex_Int != 3)
                && (tInfoClassIndex_Int != 6)
                && (tInfoClassIndex_Int != 9))*/
        {
            aDevInfoDisplay_QTextBrowser->append(aHIDUSB_c_HID_USB->aHIDInfoHead_QStrP[tInfoClassIndex_Int] + tDevInfo_Auto);
        }
        else
        {
            aDevInfoDisplay_QTextBrowser->append(aHIDUSB_c_HID_USB->aHIDInfoHead_QStrP[tInfoClassIndex_Int] + tDevInfo_Auto);
        }
        tInfoClassIndex_Int++;
    }

    //@NOTE:更新TreeView上的设备信息
    int tParentCnt_Int = 0;
    for (tParentCnt_Int = 0; xCurrentIndex_Int - aChildCnt_QList_Int.at(tParentCnt_Int) >= 0; tParentCnt_Int++)                                                     //@NOTE:以当前ComboBox所选项的Index为标准转换为第几个父类的第几个子类
    {
        xCurrentIndex_Int -= aChildCnt_QList_Int.at(tParentCnt_Int);
    }
    QModelIndex tNewCurrent_QModelIndex = aDevInfo_QStandardItemModel->item(tParentCnt_Int,0)->child(xCurrentIndex_Int,1)->index();
    aCurrentItem_QItemSelectionModel->setCurrentIndex(tNewCurrent_QModelIndex,QItemSelectionModel::SelectCurrent);
}
//@FUNC:当前TreeView所选设备发生变化时变更ComboBox所选设备的槽函数
void qHID_USB::sOn_TreeSelectChanged_Slot(QModelIndex xCurSelect,QModelIndex xPreSelect)
{
    Q_UNUSED(xPreSelect)
    if(!aOpenDev_QPushButton->isEnabled())return;                                                                                                                   //@NOTE:已经有设备被打开的清空下槽函数不响应
    if(aScanfHIDDev_Bool == true) return;                                                                                                                           //@WARN：该入参检测是必要的，否则程序将在重新扫描设备时响应槽函数，进而导致程序崩溃！！！
    if(aDevInfo_QStandardItemModel->parent(xCurSelect).isValid())                                                                                                   //@NOTE:如果当前选择的是子节点（存在父节点）
    {
        int tDevIndex_Int = 0;
        tDevIndex_Int = aDevInfo_QStandardItemModel->itemFromIndex(xCurSelect)->row();
        for(int tDevIndexCnt = 0; tDevIndexCnt < aDevInfo_QStandardItemModel->parent(xCurSelect).row(); ++tDevIndexCnt)                                             //@NOTE:那么将该子节点前的父节点所包含的子节点累加
        {
            tDevIndex_Int += aChildCnt_QList_Int.at(tDevIndexCnt);
        }
        aDevSelect_QComboBox->setCurrentIndex(tDevIndex_Int);                                                                                                       //@NOTE:最后用累加的子节点加上当前的子节点序号即可获得当前所选的子节点的index
    }

}
//@FUNC:当前所选TabWidget发生变化时用于改变界面的槽函数
void qHID_USB::sOn_TabWidgetChanged_Slot(int xNewIndex)
{
    if(aScanfHIDDev_Bool == true) return;                                                                                                                           //@WARN：该入参检测是必要的，否则程序将在重新扫描设备时响应槽函数，进而导致程序崩溃！！！

    if(xNewIndex != 1)
    {
        aTabWidget_qHIDUSB_TabWidget->setMaximumHeight(5000);
        aDockWidget_QWidget->setHidden(true);
    }
    else if(xNewIndex == 1)
    {
        aTabWidget_qHIDUSB_TabWidget->setFixedHeight(200);
        aDockWidget_QWidget->setHidden(false);
    }
    if(xNewIndex == 3)
    {
        ui->action_AppendDev->setEnabled(true);
    }else
    {
        ui->action_AppendDev->setEnabled(false);
        ui->action_DeleteDev->setEnabled(false);
    }
}
//@FUNC:设备收藏设置页所选列发生变动
void qHID_USB::sOn_DevEditCurChanged_Slot(QModelIndex xCurSelect, QModelIndex xPreSelect)
{
    Q_UNUSED(xPreSelect)
    if(aScanfHIDDev_Bool == true) return;                                                                                                                           //@WARN：该入参检测是必要的，否则程序将在重新扫描设备时响应槽函数，进而导致程序崩溃！！！
    //@NOTE:如果所选列刚好是收藏设置列，那么则反转设置按钮
    if(xCurSelect.column() == 1)                                                                                                                                    //@NOTE:如果所选列刚好是收藏设置列，那么则反转收藏设置
    {
        //@NOTE:如果所选列刚好是收藏设置列，那么则反转收藏按钮
        int tCaredState_Int = aDevInfoTable_QStandardItemModel->itemFromIndex(xCurSelect)->checkState();                                                            //@NOTE:储存Check值用于变动，避免反复调用函数造成的性能损失
        if(Qt::Unchecked == tCaredState_Int)
        {
            tCaredState_Int = Qt::Checked;
        }
        else if(Qt::Checked == tCaredState_Int)
        {
            tCaredState_Int = Qt::Unchecked;
        }
        aDevInfoTable_QStandardItemModel->itemFromIndex(xCurSelect)->setCheckState(Qt::CheckState(tCaredState_Int));                                                //@NOTE:将完成调整的Check值写入Item


        //@NOTE:写入后立马将当前所选项目移至右边，避免点错后不能立马去掉勾的现象
        aTableCurItem_QItemSelectionModel->clearCurrentIndex();
        aTableCurItem_QItemSelectionModel->clearSelection();

        //@NOTE:如果收藏Check被勾选，那么则将勾选的设备添加到收藏页
        if(Qt::Checked == tCaredState_Int)
        {
            int tInsertRow_Int = aCareDev_QSqlRelationalTableModel->rowCount();                                                                                     //@NOTE:获取收藏的设备数量
            aCareDev_QSqlRelationalTableModel->insertRow(tInsertRow_Int, QModelIndex());                                                                            //@NOTE:按照设备数量新插入行至末尾（插哪无所谓，因为Model设置了排序的）

            //@NOTE:收藏设置表格中新勾选的表格的数据拷贝到数据库表格
            for (int tInfoClass_Int = 1; tInfoClass_Int < 7; ++tInfoClass_Int)                                                                                      //@NOTE:收藏设置表格中新勾选的表格的数据拷贝到数据库表格
            {
                QModelIndex tInsertRow_QModelIndex = aCareDev_QSqlRelationalTableModel->index(tInsertRow_Int, tInfoClass_Int - 1);                                  //@NOTE:获取数据插入位置，setData函数必须要QModelIndex
                aCareDev_QSqlRelationalTableModel->setData( tInsertRow_QModelIndex,                                                                                 //@NOTE:插入的位置
                                                            aDevInfoTable_QStandardItemModel->item(xCurSelect.row(), tInfoClass_Int + 1)->data(Qt::DisplayRole),    //@NOTE:插入的数据(这里的数据类型时.data的返回值（）)
                                                            Qt::EditRole);                                                                                          //@NOTE:插入的数据Role（这里应该只能写EditRole否则不会显示）
            }

            bool tResult_Bool = aCareDev_QSqlRelationalTableModel->submitAll();
            if(!tResult_Bool)
            {
                QMessageBox::warning(this,
                                     QString::fromLocal8Bit("警告"),
                                     QString::fromLocal8Bit("【错误-0】：保存修改失败，错误信息如下所示：\n")
                                     + aCareDev_QSqlRelationalTableModel->lastError().text());
            }
        }
        else if(Qt::Unchecked == tCaredState_Int)                                                                                                                   //@NOTE:去掉勾则删除数据库中对应的设备
        {
            int tRowCnt_Int = sQueryItemForSqlModel(aDevInfoTable_QStandardItemModel->item(xCurSelect.row(), 3)->data(Qt::DisplayRole).toString());
            if(tRowCnt_Int >= 0)
            {
                aCareDev_QSqlRelationalTableModel->removeRow(tRowCnt_Int);                                                                                          //@NOTE:删除对应行的数据
                aCareDev_QSqlRelationalTableModel->submitAll();                                                                                                     //@NOTE:提交修改
            }
        }
        aScanfHIDDev_Bool = true;                                                                                                                                   //@NOTE:如果操作了收藏列那么允许自动扫描函数重新扫描设备
    }
}
//@FUNC:打开按钮被点击
bool qHID_USB::sOn_OpenBtnClicked_Slot(bool xClicked)
{
    Q_UNUSED(xClicked)
    if(aScanfHIDDev_Bool) return false;

    //@NOTE:记录当前打开的设备信息
    aCurOpendDevInfo_QStr = aDevSelect_QComboBox->currentText();
    QString tSelectDevPath_QStr = aTotalDev_QList_QStrList.at(aDevSelect_QComboBox->currentIndex()).at(c_HID_USB::cDevInfoIndex_PATH);
    aWriteThread_qHIDTXThread = new qHIDTXThread(tSelectDevPath_QStr);
    aTXReport_qHIDSendReportThread = new qHIDSendReportThread(tSelectDevPath_QStr);
    aWriteThread_qHIDTXThread->start();
    aTXReport_qHIDSendReportThread->start();

    aTabWidget_qHIDUSB_TabWidget->setCurrentIndex(cSendMSNTable);                                                                                                   //@NOTE:点击打开设备按钮后自动跳转至消息收发页

    if(ui->action_CareWithOpen->isChecked())
    {
        QModelIndex tOpenDev_QModelIndex = aDevInfoTable_QStandardItemModel->index(aDevSelect_QComboBox->currentIndex(),1);                                         //@NOTE:自动收藏开启过的设备
        if(aDevInfoTable_QStandardItemModel->itemFromIndex(tOpenDev_QModelIndex)->checkState() != Qt::Checked)
            aTableCurItem_QItemSelectionModel->setCurrentIndex(tOpenDev_QModelIndex, QItemSelectionModel::Current);
    }

    //@NOTE:延迟等待子线程开启设备函数                                                                                                                                   //@STUDY:参考https://blog.csdn.net/Viciower/article/details/122690475
    QTime tComeBackeTime_Int;
    tComeBackeTime_Int = QTime::currentTime().addMSecs(3000);                                                                                                       //@NOTE:发送函数的发送延迟！避免连续两次调用HID发送函数导致的程序假死！tComeBackeTime_InttComeBackeTime_InttComeBackeTime_InttComeBackeTime_InttComeBackeTime_InttComeBackeTime_InttComeBackeTime_InttComeBackeTime_InttComeBackeTime_Int
    while(aWriteThread_qHIDTXThread->aOpenedResult_Int == qHIDTXThread::cWait)
    {
        //@NOTE:等待发送子线程返回设备打开结果
        if(QTime::currentTime() >= tComeBackeTime_Int)
        {
            aWriteThread_qHIDTXThread->sWriteStop();                                                                                                                //@NOTE:停止子线程的消息发送
            if(aWriteThread_qHIDTXThread->isRunning())                                                                                                              //@NOTE:如果进程还在运行则强行结束线程
            {
                aWriteThread_qHIDTXThread->terminate();                                                                                                             //@NOTE:强行关闭线程
                aWriteThread_qHIDTXThread->wait();                                                                                                                  //@NOTE:回收线程
                aWriteThread_qHIDTXThread = nullptr;
            }
            //@NOTE:检测是否需要添加日期时间戳
            sRefreshDateAndTime();
            //@NOTE:设备打开提示
            QString tOpenTip_QStr = tr("【提示】:") + aCurOpendDevInfo_QStr + tr(" 打开超时！");
            aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + tOpenTip_QStr);
            //@NOTE:记录设备打开时间
            sDataAutoSave(aAutoSaveDateAndTime_QStr + tOpenTip_QStr);
            return false;
        }
    }

    //@NOTE:延迟等待子线程开启设备函数                                                                                                                                  //@STUDY:参考https://blog.csdn.net/Viciower/article/details/122690475
    tComeBackeTime_Int = QTime::currentTime().addMSecs(3000);                                                                                                      //@NOTE:发送函数的发送延迟！避免连续两次调用HID发送函数导致的程序假死！tComeBackeTime_InttComeBackeTime_InttComeBackeTime_InttComeBackeTime_InttComeBackeTime_InttComeBackeTime_InttComeBackeTime_InttComeBackeTime_InttComeBackeTime_Int
    while(aTXReport_qHIDSendReportThread->aOpenedResult_Int == qHIDTXThread::cWait)
    {
        //@NOTE:等待发送子线程返回设备打开结果
        if(QTime::currentTime() >= tComeBackeTime_Int)
        {
            aTXReport_qHIDSendReportThread->sWriteStop();                                                                                                            //@NOTE:停止子线程的消息发送
            if(aTXReport_qHIDSendReportThread->isRunning())                                                                                                          //@NOTE:如果进程还在运行则强行结束线程
            {
                aTXReport_qHIDSendReportThread->terminate();                                                                                                         //@NOTE:强行关闭线程
                aTXReport_qHIDSendReportThread->wait();                                                                                                              //@NOTE:回收线程
                aTXReport_qHIDSendReportThread = nullptr;
            }
            //@NOTE:检测是否需要添加日期时间戳
            sRefreshDateAndTime();
            //@NOTE:设备打开提示
            QString tOpenTip_QStr = tr("【提示】:") + aCurOpendDevInfo_QStr + tr(" 打开超时！");
            aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + tOpenTip_QStr);
            //@NOTE:记录设备打开时间
            sDataAutoSave(aAutoSaveDateAndTime_QStr + tOpenTip_QStr);
            return false;
        }
    }

    if(aWriteThread_qHIDTXThread->aOpenedResult_Int == qHIDTXThread::cOpenOK
            && aTXReport_qHIDSendReportThread->aOpenedResult_Int == qHIDSendReportThread::cOpenOK)
    {
        connect(aWriteThread_qHIDTXThread, SIGNAL(sSendMSNResult_Signal(int)), this, SLOT(sWriteThreadFeedDog_Slot(int)));                                          //@NOTE:看门狗饲料接收函数
        connect(aTXReport_qHIDSendReportThread, SIGNAL(sSendReportResult_Signal(int)), this, SLOT(sReportTXThreadFeedDog_Slot(int)));                                 //@NOTE:看门狗饲料接收函数
        //@NOTE:打开设备后调整按钮状态
        aOpenDev_QPushButton->setEnabled(false);
        aCloseDev_QPushButton->setEnabled(true);
        aScanDev_QPushButton->setEnabled(false);
        aDevSelect_QComboBox->setEnabled(false);
        //@VARIABLE:消息发送页组件
        aSendMSN0_QPushButton->setEnabled(true);
        aSendMSN1_QPushButton->setEnabled(true);
        aSendMSN2_QPushButton->setEnabled(true);
        aReportSend_QPushButton->setEnabled(true);
        aAutoSend0_QCheckBox->setEnabled(true);
        aAutoSend1_QCheckBox->setEnabled(true);
        aAutoSend2_QCheckBox->setEnabled(true);
        aAutoSendReport_QCheckBox->setEnabled(true);
        aDisplayMSN_QTimer->start(aRXMSNDisplayCycle_QSPinBox->value());
        aSendFailCnt_Int = 0;

        //@NOTE:开启数据自动保存
        sStartSaveWithOpenDev();

        //@NOTE:检测是否需要添加日期时间戳
        sRefreshDateAndTime();

        //@NOTE:设备打开提示
        QString tOpenTip_QStr = tr("【提示】:") + aCurOpendDevInfo_QStr + tr(" 打开成功！");
        aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + tOpenTip_QStr);

        //@NOTE:记录设备打开时间
        sDataAutoSave(aAutoSaveDateAndTime_QStr + tOpenTip_QStr);

        //@NOTE:记录被打开设备的Path
        aOpenedDevPath_QStr = tSelectDevPath_QStr;

        //@NOTE:开启接收线程
        aReadThread_qHIDRXThread = new qHIDRXThread(aOpenedDevPath_QStr, aReceiveCycle_QSPinBox->value());                                                          //@NOTE:创建消息接收线程
        connect(aReadThread_qHIDRXThread,SIGNAL(sGetMSN_Signal(QString)),this,SLOT(sOn_ReadNewMsn_Slot(QString)));                                                  //@NOTE:将接收线程的消息转发信号与主线程消息处理函数绑定
        connect(aTXReport_qHIDSendReportThread,SIGNAL(sGetReport_Signal(QString)),this,SLOT(sOn_ReadNewReport_Slot(QString)));                                        //@NOTE:将报告发送线程中用于接收GetReport消息的信号与接收槽函数绑定
        aReadThread_qHIDRXThread->start();                                                                                                                          //@NOTE:启动接收线程
        return true;
    }
    else
    {
        //@NOTE:检测是否需要添加日期时间戳
        sRefreshDateAndTime();
        //@NOTE:设备打开提示
        QString tOpenTip_QStr = tr("【提示】:") + aCurOpendDevInfo_QStr + tr(" | 【路径】:") + tSelectDevPath_QStr + tr(" | 打开失败！");
        aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + tOpenTip_QStr);
        //@NOTE:记录设备打开时间
        sDataAutoSave(aAutoSaveDateAndTime_QStr + tOpenTip_QStr);
        return false;
    }
}
//@FUNC:关闭按钮被点击
void qHID_USB::sOn_CloseBtnClicked_Slot(bool xClicked)
{
    Q_UNUSED(xClicked)
    if(aCloseDev_QPushButton->isEnabled())
    {
        aTabWidget_qHIDUSB_TabWidget->setCurrentIndex(cDevSelectTable);
        //@NOTE:关闭后调整按钮状态
        aOpenDev_QPushButton->setEnabled(true);
        aScanDev_QPushButton->setEnabled(true);
        aDevSelect_QComboBox->setEnabled(true);
        aCloseDev_QPushButton->setEnabled(false);

        aAUTOSendMSN0_QTimer->stop();
        aAUTOSendMSN1_QTimer->stop();
        aAUTOSendMSN2_QTimer->stop();
        aAUTOSetReport_QTimer->stop();
        aAutoSend0_QCheckBox->setChecked(false);
        aAutoSend1_QCheckBox->setChecked(false);
        aAutoSend2_QCheckBox->setChecked(false);
        aAutoSendReport_QCheckBox->setChecked(false);
        aSendMSN0_QPushButton->setEnabled(false);
        aSendMSN1_QPushButton->setEnabled(false);
        aSendMSN2_QPushButton->setEnabled(false);
        aAutoSend0_QCheckBox->setEnabled(false);
        aAutoSend1_QCheckBox->setEnabled(false);
        aAutoSend2_QCheckBox->setEnabled(false);
        aAutoSendReport_QCheckBox->setEnabled(false);

        aWriteThread_qHIDTXThread->sWriteStop();                                                                                                                    //@NOTE:停止子线程的消息发送
        aReadThread_qHIDRXThread->sReadStop();                                                                                                                      //@NOTE:停止子线程的消息接收
        aTXReport_qHIDSendReportThread->sWriteStop();                                                                                                               //@NOTE:停止子线程的消息发送
        //aHIDUSB_c_HID_USB->sCloseCurrentDev();                                                                                                                    //@NOTE:关闭打开的HID设备
        if(aWriteThread_qHIDTXThread->isRunning())                                                                                                                  //@NOTE:如果进程还在运行则强行结束线程
        {
            aWriteThread_qHIDTXThread->terminate();                                                                                                                 //@NOTE:强行关闭线程
            aWriteThread_qHIDTXThread->wait();                                                                                                                      //@NOTE:回收线程
            aWriteThread_qHIDTXThread = nullptr;
        }
        if(aReadThread_qHIDRXThread->isRunning())                                                                                                                   //@NOTE:如果进程还在运行则强行结束线程
        {
            aReadThread_qHIDRXThread->terminate();                                                                                                                  //@NOTE:强行关闭线程
            aReadThread_qHIDRXThread->wait();                                                                                                                       //@NOTE:回收线程
            aReadThread_qHIDRXThread = nullptr;
        }
        if(aTXReport_qHIDSendReportThread->isRunning())                                                                                                             //@NOTE:如果进程还在运行则强行结束线程
        {
            aTXReport_qHIDSendReportThread->terminate();                                                                                                            //@NOTE:强行关闭线程
            aTXReport_qHIDSendReportThread->wait();                                                                                                                 //@NOTE:回收线程
            aTXReport_qHIDSendReportThread = nullptr;
        }

        //@NOTE:检测是否需要添加日期时间戳
        sRefreshDateAndTime();

        //@NOTE:关闭设备提示
        QString tCloseTip_QStr = tr("【提示】:") + aCurOpendDevInfo_QStr + tr(" 关闭完成！");
        aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + tCloseTip_QStr);


        //@NOTE:记录设备打开时间
        sDataAutoSave(aAutoSaveDateAndTime_QStr + tCloseTip_QStr);
        //@NOTE:暂停接收消息间隔显示计数器
        aDisplayMSN_QTimer->stop();
        sStopSaveWithCloseDev();                                                                                                                                    //@NOTE:关闭数据的自动保存

        //@NOTE:清空记录
        aSendOkSize_Int = 0;
        aSendNGSize_Int = 0;
        aSendFailCnt_Int = 0;
        }
}
//@FUNC:扫描按钮被点击
void qHID_USB::sOn_ScanfBtnClicked_Slot(bool xClicked)
{
    Q_UNUSED(xClicked)
    if(aScanDev_QPushButton->isEnabled())
    {
        aScanfHIDDev_Bool = true;
        sHIDInfoUpdate_Slot();
    }
}
//@FUNC:接收到新的信息
void qHID_USB::sOn_ReadNewMsn_Slot(QString xMSN)
{
    if(aDisplayWithHex_QCheckBox->isChecked())
    {
        QByteArray tMSN_QByteArray = xMSN.toLatin1().toHex();
        xMSN = QString::fromLatin1(tMSN_QByteArray);
    }

    if(ui->action_AutoEnter->isChecked())
    {
        aMSNBuffer_QStr += xMSN;
        //@NOTE:检测是否需要添加日期时间戳
        sRefreshDateAndTime();
        if(aMSNBuffer_QStr.indexOf("\r") != -1)                                                                                                                     //@TODO:7.2022年5月11日 —— 接收到\r自动换行的功能需要添加为可选功能；
        {
            aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr
                                             + tr("【接 收】：") + aMSNBuffer_QStr);

            aMSNBuffer_QStr.replace("\r","\\r");
            aMSNBuffer_QStr.replace("\n","\\n");
            sDataAutoSave(aAutoSaveDateAndTime_QStr + tr("【接 收】：") + aMSNBuffer_QStr);                                                                           //@NOTE:接收消息自动保存
            aMSNBuffer_QStr = "";
        }
    }
    else
    {
        //@NOTE:检测是否需要添加日期时间戳
        aMSNBuffer_QStr += xMSN;
        if(aDisplayMSNIndex_Bool)
        {
            sRefreshDateAndTime();
            aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr
                                                + tr("【接 收】：") + aMSNBuffer_QStr);
            aMSNBuffer_QStr.replace("\r","\\r");
            aMSNBuffer_QStr.replace("\n","\\n");
            sDataAutoSave(aAutoSaveDateAndTime_QStr + tr("【接 收】：") + aMSNBuffer_QStr);                                                                           //@NOTE:接收消息自动保存
            aMSNBuffer_QStr = "";
            aDisplayMSNIndex_Bool = false;
        }
    }
}
//@FUNC:GetReport消息接收函数
void qHID_USB::sOn_ReadNewReport_Slot(QString xReport)
{
    //@NOTE:检测是否需要添加日期时间戳
    aReportBuffer_QStr += xReport;
    if(aDisplayMSNIndex_Bool)
    {
        sRefreshDateAndTime();
        aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr
                                            + tr("【接 收】：") + aReportBuffer_QStr);
        aReportBuffer_QStr.replace("\r","\\r");
        aReportBuffer_QStr.replace("\n","\\n");
        sDataAutoSave(aAutoSaveDateAndTime_QStr + tr("【接 收】：") + aReportBuffer_QStr);                                                                            //@NOTE:接收消息自动保存
        aReportBuffer_QStr = "";
        aDisplayMSNIndex_Bool = false;
    }
}
//@FUNC:发送按钮0被点击
void qHID_USB::sOn_SendBtn0Clicked_Slot()
{
    QString tSendMSN_QStr = aMSNEdit0_QPlainTextEdit->document()->toPlainText();
    if(aHexModel0_QCheckBox->isChecked())
    {
        tSendMSN_QStr = tSendMSN_QStr.replace(" ","");
    }
    sSendMSN(tSendMSN_QStr, 0, 0, (int)aHexModel0_QCheckBox->isChecked());
}
//@FUNC:发送按钮1被点击
void qHID_USB::sOn_SendBtn1Clicked_Slot()
{
    QString tSendMSN_QStr = aMSNEdit1_QPlainTextEdit->document()->toPlainText();
    if(aHexModel1_QCheckBox->isChecked())
    {
        tSendMSN_QStr = tSendMSN_QStr.replace(" ","");
    }
    sSendMSN(tSendMSN_QStr, 1, 0, (int)aHexModel1_QCheckBox->isChecked());
}
//@FUNC:发送按钮2被点击
void qHID_USB::sOn_SendBtn2Clicked_Slot()
{
    QString tSendMSN_QStr = aMSNEdit2_QPlainTextEdit->document()->toPlainText();
    if(aHexModel2_QCheckBox->isChecked())
    {
        tSendMSN_QStr = tSendMSN_QStr.replace(" ","");
    }
    sSendMSN(tSendMSN_QStr, 2, 0, (int)aHexModel2_QCheckBox->isChecked());
}
//@FUNC:16进制输入复选框0被勾选
void qHID_USB::sOn_OnHexInput0Clicked_Slot(bool xClicked_Bool)
{
    if(xClicked_Bool)
    {
        QString tHexInput_QStr = sInputToHex(aMSNEdit0_QPlainTextEdit->document()->toPlainText());
        tHexInput_QStr = sInputHexAutoSpace(tHexInput_QStr,aHexInputModel0_QComboBox->currentIndex());
        aMSNEdit0_QPlainTextEdit->clear();
        aMSNEdit0_QPlainTextEdit->appendPlainText(tHexInput_QStr);
        connect(aMSNEdit0_QPlainTextEdit, SIGNAL(textChanged()), this, SLOT(sOn_OnMSNEdit0Changed_Slot()));                                                         //@FUNC:当消息输入框0文本变化时
    }
    else if(!xClicked_Bool && aInitOver_Bool)
    {
        aMSNEdit0_QPlainTextEdit->clear();
        disconnect(aMSNEdit0_QPlainTextEdit, SIGNAL(textChanged()), this, SLOT(sOn_OnMSNEdit0Changed_Slot()));                                                      //@FUNC:当消息输入框0文本变化时
    }
}
//@FUNC:16进制输入复选框1被勾选
void qHID_USB::sOn_OnHexInput1Clicked_Slot(bool xClicked_Bool)
{
    if(xClicked_Bool)
    {
        QString tHexInput_QStr = sInputToHex(aMSNEdit1_QPlainTextEdit->document()->toPlainText());
        tHexInput_QStr = sInputHexAutoSpace(tHexInput_QStr,aHexInputModel1_QComboBox->currentIndex());
        aMSNEdit1_QPlainTextEdit->clear();
        aMSNEdit1_QPlainTextEdit->appendPlainText(tHexInput_QStr);
        connect(aMSNEdit1_QPlainTextEdit, SIGNAL(textChanged()), this, SLOT(sOn_OnMSNEdit1Changed_Slot()));                                                         //@FUNC:当消息输入框1文本变化时
    }
    else if(!xClicked_Bool && aInitOver_Bool)
    {
        aMSNEdit1_QPlainTextEdit->clear();
        disconnect(aMSNEdit1_QPlainTextEdit, SIGNAL(textChanged()), this, SLOT(sOn_OnMSNEdit1Changed_Slot()));                                                      //@FUNC:当消息输入框1文本变化时
    }
}
//@FUNC:16进制输入复选框2被勾选
void qHID_USB::sOn_OnHexInput2Clicked_Slot(bool xClicked_Bool)
{
    if(xClicked_Bool)
    {
        QString tHexInput_QStr = sInputToHex(aMSNEdit2_QPlainTextEdit->document()->toPlainText());
        tHexInput_QStr = sInputHexAutoSpace(tHexInput_QStr,aHexInputModel2_QComboBox->currentIndex());
        aMSNEdit2_QPlainTextEdit->clear();
        aMSNEdit2_QPlainTextEdit->appendPlainText(tHexInput_QStr);
        connect(aMSNEdit2_QPlainTextEdit, SIGNAL(textChanged()), this, SLOT(sOn_OnMSNEdit2Changed_Slot()));                                                         //@FUNC:当消息输入框2文本变化时
    }
    else if(!xClicked_Bool && aInitOver_Bool)
    {
        aMSNEdit2_QPlainTextEdit->clear();
        disconnect(aMSNEdit2_QPlainTextEdit, SIGNAL(textChanged()), this, SLOT(sOn_OnMSNEdit2Changed_Slot()));                                                      //@FUNC:当消息输入框2文本变化时
    }
}
//@FUNC:当消息输入框0文本变化时
void qHID_USB::sOn_OnMSNEdit0Changed_Slot()
{
    if(aHexModel0_QCheckBox->isChecked())
    {
        disconnect(aMSNEdit0_QPlainTextEdit, SIGNAL(textChanged()), this, SLOT(sOn_OnMSNEdit0Changed_Slot()));                                                      //@FUNC:因为本函数会对文本输入框进行修改所以将断开信号与槽的连接避免反复调用
        QString tInputHex_QStr = sInputToHex(aMSNEdit0_QPlainTextEdit->document()->toPlainText());
        tInputHex_QStr = sInputHexAutoSpace(tInputHex_QStr,aHexInputModel0_QComboBox->currentIndex());
        aMSNEdit0_QPlainTextEdit->clear();
        aMSNEdit0_QPlainTextEdit->appendPlainText(tInputHex_QStr);
        connect(aMSNEdit0_QPlainTextEdit, SIGNAL(textChanged()), this, SLOT(sOn_OnMSNEdit0Changed_Slot()));                                                         //@FUNC:完成字符串修改后重新连接信号与槽
    }
}
//@FUNC:当消息输入框1文本变化时
void qHID_USB::sOn_OnMSNEdit1Changed_Slot()
{
    if(aHexModel1_QCheckBox->isChecked())
    {
        disconnect(aMSNEdit1_QPlainTextEdit, SIGNAL(textChanged()), this, SLOT(sOn_OnMSNEdit1Changed_Slot()));                                                      //@FUNC:因为本函数会对文本输入框进行修改所以将断开信号与槽的连接避免反复调用
        QString tInputHex_QStr = sInputToHex(aMSNEdit1_QPlainTextEdit->document()->toPlainText());
        tInputHex_QStr = sInputHexAutoSpace(tInputHex_QStr,aHexInputModel1_QComboBox->currentIndex());
        aMSNEdit1_QPlainTextEdit->clear();
        aMSNEdit1_QPlainTextEdit->appendPlainText(tInputHex_QStr);
        connect(aMSNEdit1_QPlainTextEdit, SIGNAL(textChanged()), this, SLOT(sOn_OnMSNEdit1Changed_Slot()));                                                         //@FUNC:完成字符串修改后重新连接信号与槽
    }
}
//@FUNC:当消息输入框2文本变化时
void qHID_USB::sOn_OnMSNEdit2Changed_Slot()
{
    if(aHexModel2_QCheckBox->isChecked())
    {
        disconnect(aMSNEdit2_QPlainTextEdit, SIGNAL(textChanged()), this, SLOT(sOn_OnMSNEdit2Changed_Slot()));                                                      //@FUNC:因为本函数会对文本输入框进行修改所以将断开信号与槽的连接避免反复调用
        QString tInputHex_QStr = sInputToHex(aMSNEdit2_QPlainTextEdit->document()->toPlainText());
        tInputHex_QStr = sInputHexAutoSpace(tInputHex_QStr,aHexInputModel2_QComboBox->currentIndex());
        aMSNEdit2_QPlainTextEdit->clear();
        aMSNEdit2_QPlainTextEdit->appendPlainText(tInputHex_QStr);
        connect(aMSNEdit2_QPlainTextEdit, SIGNAL(textChanged()), this, SLOT(sOn_OnMSNEdit2Changed_Slot()));                                                         //@FUNC:完成字符串修改后重新连接信号与槽
    }
}
//@FUNC:当16进制自动空格模式变化时0
void qHID_USB::sOn_OnHexModel0Changed_Slot()
{
    if(!aHexModel0_QCheckBox->isChecked())
    {
        aHexModel0_QCheckBox->setChecked(true);
        sOn_OnHexInput0Clicked_Slot(aHexModel0_QCheckBox->isChecked());
    }
    else
    {
        sOn_OnMSNEdit0Changed_Slot();
    }
}
//@FUNC:当16进制自动空格模式变化时1
void qHID_USB::sOn_OnHexModel1Changed_Slot()
{
    if(!aHexModel1_QCheckBox->isChecked())
    {
        aHexModel1_QCheckBox->setChecked(true);
        sOn_OnHexInput1Clicked_Slot(aHexModel1_QCheckBox->isChecked());
    }
    else
    {
        sOn_OnMSNEdit1Changed_Slot();
    }
}
//@FUNC:当16进制自动空格模式变化时2
void qHID_USB::sOn_OnHexModel2Changed_Slot()
{
    if(!aHexModel2_QCheckBox->isChecked())
    {
        aHexModel2_QCheckBox->setChecked(true);
        sOn_OnHexInput2Clicked_Slot(aHexModel2_QCheckBox->isChecked());
    }
    else
    {
        sOn_OnMSNEdit2Changed_Slot();
    }
}
//@FUNC:如果自动发送按钮被打开
void qHID_USB::sOn_AutoSend0CheckedChanged_Slot(bool xChecked)
{
    if(xChecked)
    {
        aAUTOSendMSN0_QTimer->start(aAutoSend0_QSpinBox->value());
    }
    else
    {
        aAUTOSendMSN0_QTimer->stop();
    }
}
//@FUNC:如果自动发送按钮被打开
void qHID_USB::sOn_AutoSend1CheckedChanged_Slot(bool xChecked)
{
    if(xChecked)
    {
        aAUTOSendMSN1_QTimer->start(aAutoSend1_QSpinBox->value());
    }
    else
    {
        aAUTOSendMSN1_QTimer->stop();
    }
}
//@FUNC:如果自动发送按钮被打开
void qHID_USB::sOn_AutoSend2CheckedChanged_Slot(bool xChecked)
{
    if(xChecked)
    {
        aAUTOSendMSN2_QTimer->start(aAutoSend2_QSpinBox->value());
    }
    else
    {
        aAUTOSendMSN2_QTimer->stop();
    }
}
//@FUNC:定时器时间变化
void qHID_USB::sOn_TimerSpinBox0ValueChanged_Slot(int xNewValue)
{
    if(aAutoSend0_QCheckBox->isChecked())
    {
        aAUTOSendMSN0_QTimer->start(xNewValue);
    }
}
//@FUNC:定时器时间变化
void qHID_USB::sOn_TimerSpinBox1ValueChanged_Slot(int xNewValue)
{
    if(aAutoSend1_QCheckBox->isChecked())
    {
        aAUTOSendMSN1_QTimer->start(xNewValue);
    }
}
//@FUNC:定时器时间变化
void qHID_USB::sOn_TimerSpinBox2ValueChanged_Slot(int xNewValue)
{
    if(aAutoSend2_QCheckBox->isChecked())
    {
        aAUTOSendMSN2_QTimer->start(xNewValue);
    }
}
//@FUNC:消息自动接收频率变动
void qHID_USB::sOn_ReceiveCycleChaged_Slot(int xNewCycle_Int)
{
    if(aReadThread_qHIDRXThread != nullptr)
        aReadThread_qHIDRXThread->sAdjustReceiveCycle(xNewCycle_Int);
}
//@FUNC:当Report输入框有输入时
void qHID_USB::sOn_ReportEditInput_Slot(QString xNewInput)
{
    aReportEdit_QLineEdit->setText(sInputHexAutoSpace(xNewInput,aSetReportAutoAddSpace_QComboBox->currentIndex()));
}
//@FUNC:发送报告按钮被点击
void qHID_USB::sOn_SendReportBtnClicked_Slot()
{
    sSendReport(aReportEdit_QLineEdit->text(),aSelectReportModel_QComboBox->currentIndex());
}
//@FUNC:如果自动发送Report按钮被打开
void qHID_USB::sOn_AutoSendReportCheckedChanged_Slot(bool xChecked)
{

    if(xChecked)
    {
        aAUTOSetReport_QTimer->start(aAutoSetReport_QSpinBox->value());
    }
    else
    {
        aAUTOSetReport_QTimer->stop();
    }
}
//@FUNC:定时器时间变化
void qHID_USB::sOn_SendReportSpinBoxValueChanged_Slot(int xNewValue)
{
    if(aAutoSendReport_QCheckBox->isChecked())
    {
        aAUTOSetReport_QTimer->start(xNewValue);
    }
}
//@FUNC:Report16进制输入框空格模式变化
void qHID_USB::sOn_OnReportHexModelChanged_Slot(int xHexModel_Int)
{
    aReportEdit_QLineEdit->setText(sInputHexAutoSpace(aReportEdit_QLineEdit->text(),xHexModel_Int));
}
//@FUNC:输入16进制自动添加间隔的函数
QString qHID_USB::sInputHexAutoSpace(QString xNewInput, int xSpaceModel)
{
    if(xNewInput.count() == 0)return xNewInput;
    if(xSpaceModel == cManualSpece)
    {
        return xNewInput;                                                                                                                                           //@NOTE:如果用户选择的手动间隔模式，那么则不进行处理
    }

    xNewInput = xNewInput.replace(" ","");
    QString tResult_QStr = "";

    if(xNewInput.count() >= (xSpaceModel*cSpaceUnit))                                                                                                               //@NOTE:刚好处于间隔位则在末尾添加空格
    {
        for(int tInputIndex_Int = 0; tInputIndex_Int < (xNewInput.count() / (xSpaceModel*cSpaceUnit)); ++tInputIndex_Int)
        {
            tResult_QStr += xNewInput.mid(tInputIndex_Int * (xSpaceModel*cSpaceUnit), (xSpaceModel*cSpaceUnit)) + " ";
        }
    }
    if(xNewInput.count() % (xSpaceModel*cSpaceUnit) != 0)                                                                                                           //@NOTE:没有处于间隔位则直接累加余数不为整除部分的字符
    {
        tResult_QStr += xNewInput.mid(xNewInput.count() / (xSpaceModel*cSpaceUnit) * (xSpaceModel*cSpaceUnit), (xSpaceModel*cSpaceUnit));
    }

    if(tResult_QStr.mid(tResult_QStr.count()-1,1) == " ")                                                                                                           //@NOTE:删除末尾的空格
        tResult_QStr = tResult_QStr.mid(0,tResult_QStr.count()-1);
    return tResult_QStr;
}
//@FUNC:用于将输入强制转换为16进制字符的函数
QString qHID_USB::sInputToHex(QString xInput_QStr)
{
    QByteArray tInput_QByteArray = xInput_QStr.toLocal8Bit();
    QByteArray tHex_QByteArray;
    int tInputCnt_Int = xInput_QStr.count();
    int tNewArrayCnt_Int = 0;
    if(tInputCnt_Int != 0)
    {
        for (int tArrayIndex_Int = 0; tArrayIndex_Int < (tInputCnt_Int); ++tArrayIndex_Int)
        {
            if((tInput_QByteArray[tArrayIndex_Int] >= '0' && tInput_QByteArray[tArrayIndex_Int] <= '9')
                    || (tInput_QByteArray[tArrayIndex_Int] >= 'a' && tInput_QByteArray[tArrayIndex_Int] <= 'f')
                    || (tInput_QByteArray[tArrayIndex_Int] >= 'A' && tInput_QByteArray[tArrayIndex_Int] <= 'F'))
            {
                tHex_QByteArray[tNewArrayCnt_Int++] = tInput_QByteArray[tArrayIndex_Int];
            }
        }
        return QString::fromLocal8Bit(tHex_QByteArray);
    }
    else
    {
        return tInput_QByteArray;
    }
}
//@FUNC:报告发送函数
void qHID_USB::sSendReport(QString xReport_QStr, int xSendReportModel_Int)
{
    //@STUDY:16进制型QString转16进制数
    QStringList tReport_QStrList = xReport_QStr.split(" ");
    QByteArray tReport_QByteArray;
    QString tReport_QStr = xReport_QStr;
    foreach (QString tReport_QStr, tReport_QStrList) {
        tReport_QByteArray.append(QByteArray::fromHex(tReport_QStr.toLatin1()));
    }
    //@NOTE:检测是否需要添加日期时间戳
    sRefreshDateAndTime();

    bool tSendResult_Bool = aTXReport_qHIDSendReportThread->sReportSend(tReport_QByteArray,xSendReportModel_Int);
    //@NOTE:延迟发送函数  //@STUDY:参考https://blog.csdn.net/Viciower/article/details/122690475
    QTime tComeBackeTime_Int = QTime::currentTime().addMSecs(aDevWriteCycle_QSpinBox->value());                                                                     //@NOTE:发送函数的发送延迟！避免连续两次调用HID发送函数导致的程序假死！
    while(QTime::currentTime() < tComeBackeTime_Int)
    {
        //@WARN：完成发送后等待1ms，HIDAPI短时间内调用两次hid_write()会导致程序卡死，所以设置等待函数
        //@TODO:2022年5月12日——其实这个问题通过多线程是可以解决的，但是程序开发已经接近尾声了，完全没有再改的欲望所以就通过延时避免发送装车绕过问题把！
        //@NOTE:猜测延时参数和PC的性能有关，性能越差延时应该越大！但是延迟越大连续发送多条消息时定时器的偏移量也就越大例如同时两个通道定时100ms发送指令，延时参数为20ms时，如果两个通道发送撞车那么理论最大延迟可达120ms；
        //@STUDY:2022年5月17日 —— 感觉不出意外应该是找到问题了……应该是因为子线程和主线程同时调用HID设备结构体导致……
    }
    if(aSendFailCnt_Int < 10)
        aReportTXThreadWatchDog_QTimer->start(1000);
    //int tSendSize_Int;
    if(tSendResult_Bool == true)
    {
        aSendFailCnt_Int = 0;
        //tSendSize_Int = tReport_QStrList.count();
        //@TODO:预留做字节数统计的区域

        if(xSendReportModel_Int == cSetReport)
        {
            tReport_QStr = tr("【SetReport】：")
                            + tReport_QStr;
        }
        else
        {
            tReport_QStr = tr("【GetReport】：")
                            + tReport_QStr;
        }

        if(ui->action_DisplaySend->isChecked())                                                                                                                     //@NOTE:显示发送是否启用
            aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + tReport_QStr);
    }
    else
    {
        aSendFailCnt_Int++;
        aSendNGSize_Int += 1;
        aSendNGSize_QLabel->setText(tr("已发送失败次数： ") + QString::asprintf("%d",aSendNGSize_Int));
        //tSendSize_Int = tReport_QStrList.count();
        if(xSendReportModel_Int == cSetReport)
        {
            tReport_QStr = tr("【提示】：通过[SetReport]发送[")
                        + tReport_QStr
                        + tr("] 失败！适当降低发送频率可以解决该问题！");
        }
        else
        {
            tReport_QStr = tr("【提示】：通过[GetReport]发送[")
                        + tReport_QStr
                        + tr("] 失败！适当降低发送频率可以解决该问题！");
        }
        aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + tReport_QStr);
    }
    sDataAutoSave(aAutoSaveDateAndTime_QStr + tReport_QStr);
    tReport_QStr = "";
}
//@FUNC:自动扫描频率变动
void qHID_USB::sOn_AutoScanfCycleChaged_Slot(int xNewCycle_Int)
{
    aAUTOScanHIDDev_QTimer->start(xNewCycle_Int);
}
//@FUNC:发送函数间隔延迟变动
void qHID_USB::sOn_SendMSNMsDelayChaged_Slot(int xNewSendDelay_Int)
{
    aHIDUSB_c_HID_USB->sSetSendMSNMsDelay(xNewSendDelay_Int);
}
//@FUNC:接收计时器调节器数值变动
void qHID_USB::sOn_RXTimerSpinBoxValueChanged_Slot(int xNewValue)
{
    if(!aOpenDev_QPushButton->isEnabled())
    {
        aDisplayMSN_QTimer->start(xNewValue);
    }
}
//@FUNC:接收计时器超时
void qHID_USB::sOn_RXTimerTimteout_Slot()
{
    aDisplayMSNIndex_Bool = true;
}
//@FUNC:看门狗饿死了！(按照当前发送参数重启设备)
void qHID_USB::sOn_WriteThreadWatchDogTimeout_Slot()
{
    //@NOTE:检测是否需要添加日期时间戳
    sRefreshDateAndTime();
    //@NOTE:设备打开提示
    QString tOpenTip_QStr = tr("【警告】:") + aCurOpendDevInfo_QStr + tr(" 检测到发送线程死锁，正在尝试重启发送线程！");
    aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + tOpenTip_QStr);
    //@NOTE:记录设备打开时间
    sDataAutoSave(aAutoSaveDateAndTime_QStr + tOpenTip_QStr);
    aWriteThreadWatchDog_QTimer->stop();
    aReportTXThreadWatchDog_QTimer->stop();
    bool tAutoSend0_Bool = aAutoSend0_QCheckBox->isChecked();
    bool tAutoSend1_Bool = aAutoSend1_QCheckBox->isChecked();
    bool tAutoSend2_Bool = aAutoSend2_QCheckBox->isChecked();
    bool tAutoSendRepor_Bool = aAutoSendReport_QCheckBox->isChecked();
    sOn_CloseBtnClicked_Slot(true);
    for(int tRestartCnt_Int = 0; tRestartCnt_Int < 10; tRestartCnt_Int++)
    {
        if(sOn_OpenBtnClicked_Slot(true))
        {
            aAutoSend0_QCheckBox->setChecked(tAutoSend0_Bool);
            aAutoSend1_QCheckBox->setChecked(tAutoSend1_Bool);
            aAutoSend2_QCheckBox->setChecked(tAutoSend2_Bool);
            sOn_AutoSend0CheckedChanged_Slot(tAutoSend0_Bool);
            sOn_AutoSend1CheckedChanged_Slot(tAutoSend1_Bool);
            sOn_AutoSend2CheckedChanged_Slot(tAutoSend2_Bool);

            aAutoSendReport_QCheckBox->setChecked(tAutoSendRepor_Bool);
            sOn_AutoSendReportCheckedChanged_Slot(tAutoSendRepor_Bool);
            return;
        }
    }
}
//@FUNC:发送线程的看门狗饲料接收函数
void qHID_USB::sWriteThreadFeedDog_Slot(int xSendResult_Int)
{
    if(xSendResult_Int == -1)
    {
        aSendNGSize_Int -= xSendResult_Int;
        aSendNGSize_QLabel->setText(tr("已发送失败次数： ") + QString::asprintf("%d",aSendNGSize_Int));
        /*if(aSendNGSize_Int % 16 == 15)
        {
            aDevCheck_Bool = true;
        }*/

        //@NOTE:检测是否需要添加日期时间戳
        sRefreshDateAndTime();
        QString tMSN_QStr = tr("【提示】：消息发送失败！该设备可能不支持通信！");
        aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + tMSN_QStr);
        tMSN_QStr.replace("\r","\\r");
        tMSN_QStr.replace("\n","\\n");
        sDataAutoSave(aAutoSaveDateAndTime_QStr + tMSN_QStr);
    }
    else
    {
        aSendOkSize_Int += xSendResult_Int;
        aSendOkSize_QLabel->setText(tr("已成功发送字节数： ") + QString::asprintf("%d",aSendOkSize_Int));
    }
    aWriteThreadWatchDog_QTimer->stop();                                                                                                                            //@NOTE:喂狗成功则关闭看门狗
}
//@FUNC:报告发送线程的看门狗饲料接收函数
void qHID_USB::sReportTXThreadFeedDog_Slot(int xSendResult_Int)
{
    if(xSendResult_Int == -1)
    {
        aSendNGSize_Int -= xSendResult_Int;
        aSendNGSize_QLabel->setText(tr("已发送失败次数： ") + QString::asprintf("%d",aSendNGSize_Int));
        /*if(aSendNGSize_Int % 16 == 15)
        {
            aDevCheck_Bool = true;
        }*/

        //@NOTE:检测是否需要添加日期时间戳
        sRefreshDateAndTime();
        QString tMSN_QStr = tr("【提示】：消息发送失败！发送数据超长或者不符合规范！");
        aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + tMSN_QStr);
        tMSN_QStr.replace("\r","\\r");
        tMSN_QStr.replace("\n","\\n");
        sDataAutoSave(aAutoSaveDateAndTime_QStr + tMSN_QStr);
    }
    else
    {
        if(aSelectReportModel_QComboBox->currentIndex() == cSetReport)
        {
            //@NOTE:检测是否需要添加日期时间戳
            sRefreshDateAndTime();
            QString tMSN_QStr = tr("【提示】：SetReport成功，数据返回请通过BusHound查看！");
            aMSNDisplay_QTextBrowser->append(aDateAndTimeInfo_QStr + tMSN_QStr);
            tMSN_QStr.replace("\r","\\r");
            tMSN_QStr.replace("\n","\\n");
            sDataAutoSave(aAutoSaveDateAndTime_QStr + tMSN_QStr);
        }
        aSendOkSize_Int += xSendResult_Int;
        aSendOkSize_QLabel->setText(tr("已成功发送字节数： ") + QString::asprintf("%d",aSendOkSize_Int));
    }
    aReportTXThreadWatchDog_QTimer->stop();
}
//@FUNC:用于根据所选项启用禁用操作按钮的槽函数
void qHID_USB::sOn_CaredTableSelectionChanged_Slot(QModelIndex xCurItem, QModelIndex xPreItem)
{
    Q_UNUSED(xPreItem)
    if(xCurItem.row() < 0)
    {
        ui->action_DeleteDev->setEnabled(false);
    }
    else
    {
        ui->action_Uodo->setEnabled(aCareDev_QSqlRelationalTableModel->isDirty());
        ui->action_DeleteDev->setEnabled(true);
    }
}
//@FUNC:消息显示框文本变化时触发，用于避免文本数量过多
void qHID_USB::sOn_TextBrowserTextChanged()
{
    int tDisplayCnt_Int = aMSNDisplay_QTextBrowser->document()->toPlainText().count();
    int tClearCnt_Int = tDisplayCnt_Int * 100 / cTextBrowser;
    aAutoClearTextCnt_QProgressBar->setValue(tClearCnt_Int);
    if(tDisplayCnt_Int >= cTextBrowser)
    {
        aMSNDisplay_QTextBrowser->clear();
    }
}
//@FUNC:日志文件夹路径选择
void qHID_USB::on_action_PathSelect_triggered()
{
    aAutoSavePath_QStr = QFileDialog::getExistingDirectory(this,
                                                           tr("请选择日志保存路径"),
                                                           ".");
    if(aAutoSavePath_QStr.isEmpty())                                                                                                                                //@NOTE:如果没有选择将直接使用默认路径
    {
        QMessageBox::warning(this,
                             tr("【警告】"),
                             tr("你没有选择路径，程序将使用默认路径！"));
        on_action_ClearPath_triggered();
        return;
    }
    aAutoSavePath_QStr += "/";
    aAutoSavePath_QLabel->setText(tr("数据自动保存路径：") + aAutoSavePath_QStr);                                                                                      //@NOTE:更新状态栏路径显示
}
//@FUNC:打开当前日志文件夹
void qHID_USB::on_action_LogDir_triggered()
{

    QString tLogPath_QStr;
    if(aAutoSavePath_QStr.isEmpty())
    {
        on_action_ClearPath_triggered();
        tLogPath_QStr = aAutoSavePath_QStr;
        tLogPath_QStr.replace("/", "\\");
        //QDesktopServices::openUrl(QUrl(tLogPath_QStr ,QUrl::TolerantMode));                                                                                       //@NOTE:另外一种打开资源管理器的办法
    }
    else{
        QDir tLogPath_QDir(aAutoSavePath_QStr);
        tLogPath_QStr = tLogPath_QDir.absolutePath();
        tLogPath_QStr += "/";
        tLogPath_QStr.replace("/", "\\");
    }

    //@NOTE:打开文件管理器路径
    QProcess::startDetached("explorer " + tLogPath_QStr);                                                                                                           //@WARNING:提示弃用请及时更换写法
}
//@FUNC:恢复日志储存路径为默认路径
void qHID_USB::on_action_ClearPath_triggered()
{
    aAutoSavePath_QStr = QDir::currentPath() + "/Log/";
    QDir tAutoSavePath0_QDir(aAutoSavePath_QStr);
    if(!tAutoSavePath0_QDir.exists())
    {
        QDir tCurPath0_QDir(QDir::currentPath());
        if(!tCurPath0_QDir.mkdir("Log"))
        {
            QMessageBox::warning(this,
                                 tr("【警告】"),
                                 tr("日志文件夹创建失败！自动保存将无法启用！"));
            aAutoSavePath_QStr = "";
        }
    }
    aAutoSavePath_QStr = aAutoSavePath_QStr + "LOG_HIDUSB/";
    QDir tAutoSavePath1_QDir(aAutoSavePath_QStr);
    if(!tAutoSavePath1_QDir.exists())
    {
        QDir tCurPath1_QDir(QDir::currentPath());
        if(!tCurPath1_QDir.mkdir("Log/LOG_HIDUSB"))
        {
            QMessageBox::warning(this,
                                 tr("【警告】"),
                                 tr("日志文件夹创建失败！自动保存将无法启用！"));
            aAutoSavePath_QStr = "";
        }
    }
    aAutoSavePath_QLabel->setText(tr("数据自动保存路径：") + aAutoSavePath_QStr);                                                                                      //@NOTE:更新状态栏路径显示
}
//@FUNC:清空文本框按钮槽函数
void qHID_USB::on_action_ClearTextBrow_triggered()
{
    aMSNDisplay_QTextBrowser->clear();
}
//@FUNC:关于本程序的相关信息
void qHID_USB::on_action_AboutApp_triggered()
{
    /*QString tAboutAppPath_QStr = QDir("./").absolutePath() + "/About/AbotAppInfo_0.txt";
    QFile tAboutApp0_QFile(tAboutAppPath_QStr);
    if(!tAboutApp0_QFile.open(QIODevice::ReadOnly))
    {
        QMessageBox::warning(this,
                             tr("【警告】"),
                             tr("软件信息文件加载出错！"));
    }
    QString tAboutApp_QStr = tAboutApp0_QFile.readAll();*/

    /*QString msg = "BUG Reporting:<a href='https://www.icode9.com/content-4-1190299.html'>Github</a><br>"                                                          //@STUDY:如何给文本插入超链接
                  "Update:<a href='https://download.csdn.net/download/duckSoup_2001/xxx'>CSDN</a><br>"
                  "E-mail:xuronghua2001@outlook.com" ;
    QMessageBox::about(nullptr,"关于",msg);*/

    QMessageBox::about(this,
                       tr("【关于本模块】(1/3)"),
                       tr("软件名称：PB-Box HIDUSB模块\n")
                       + tr("软件版本：") + aVersion_QStr
                       + tr("\n版本发布时间：") + aReleaseTime_QStr
                       + tr("\n首次发布时间：2022年05月07日\n")
                       + tr("作者：Spectre\n\n\n")
                       //+ tAboutApp_QStr
                       + tr("【应用简介】：\n1.该程序为PB-Box项目的一部分，是PB-Box中用于和USB HID设备通信的调试工具；\n")
                       + tr("2.本程序和USB HID设备的通信是通过HIDAPI库实现的，故理论上是支持跨平台的。当然后面如果有空我会进行跨平台的测试的，不过目前的话就暂时只有Windows版本的；\n")
                       + tr("3.开发PB-Box的初衷就是对所学的Qt知识进行复习和查漏补缺，所以程序的设计风格更加偏向于花里胡哨而不是稳定性和性能，所以该程序对于性能还是有一定的需求的；\n\n")
                       + tr("【应用声明】:\n1.本软件大量使用了iconfont网站的图标（万分感谢各图标的作者！），如有侵权请联系删除；\n")
                       + tr("2.本软件的最终解释权归Spectre所有；\n")
                       + tr("3.本软件的源码已经上传至我的Gitee仓库，最新打包文件已经上传至蓝奏云，详细信息请查阅【检查更新】页；\n")
                       );
    //tAboutApp0_QFile.close();

    /*tAboutAppPath_QStr = QDir("./").absolutePath() + "/About/AbotAppInfo_1.txt";
    QFile tAboutApp1_QFile(tAboutAppPath_QStr);
    if(!tAboutApp1_QFile.open(QIODevice::ReadOnly))
    {
        QMessageBox::warning(this,
                             tr("【警告】"),
                             tr("软件信息文件加载出错！"));
    }
    tAboutApp_QStr = tAboutApp1_QFile.readAll();*/

    QMessageBox::about(this,
                       tr("【关于本模块】(2/3)"),
                       //tAboutApp_QStr
                       tr("【程序特色】：\n1.本程序具备自动扫描功能，且会将扫描到的设备信息分析、整理、排序；\n")
                       + tr("2.本程序可自行收藏常用设备，避免了重复选择设备带来的困扰；\n")
                       + tr("3.本程序拥有三个指令发送框，且会根据换行符自动将发送内容分割为多条指令进行发送，同时支持GetFeature以及SetFeature两种简单的控制传输通信；\n")
                       + tr("4.本程序的接收部分是交由子线程无阻塞接收的，为避免性能浪费最低接收间隔为1ms；\n")
                       + tr("5.本程序默认使用接收自动换行，即收到换行符后才会显示接收信息。如果你接收的内容没有换行符，则需要你在设置中自行关闭自动换行功能，再通过调节接收间隔来控制换行的频率；\n")
                       + tr("6.本程序三个指令发送框都拥有独立的自动发送定时器；\n")
                       + tr("7.本程序从打开设备开始将会自动记录完整的通信数据；\n")
                       + tr("8.本程序支持界面参数自动保存功能；\n")
                       + tr("9.本程序拥有四个调节器，它们的功能如下所示：\n\t①.消息接收间隔：接收线程休眠时间；\n\t②.接收显示间隔：消息缓冲区刷新频率；\n\t③.设备扫描间隔：设备信息自动扫描频率；\n\t④.消息发送间隔：消息发送等待时间；\n\n"
                           "PS:消息发送间隔实际上是主线程的强制休眠，因此在不出错的情况下该值越小越好。但是该值过小将导致HIDAPI函数出现死锁，所以请根据使用情况自行调整）\n")
                       );

    //tAboutApp1_QFile.close();

    /*tAboutAppPath_QStr = QDir("./").absolutePath() + "/About/AbotAppInfo_2.txt";
    QFile tAboutApp2_QFile(tAboutAppPath_QStr);
    if(!tAboutApp2_QFile.open(QIODevice::ReadOnly))
    {
        QMessageBox::warning(this,
                             tr("【警告】"),
                             tr("软件信息文件加载出错！"));
    }
    tAboutApp_QStr = tAboutApp2_QFile.readAll();*/

    QMessageBox::about(this,
                       tr("【关于本模块】(3/3)"),
                       //+ tAboutApp_QStr
                       tr("【已知问题】：\n1.在挂机测试的过程中发现，如果PC负载过高，将有概率出现程序死锁于HIDAPI的发送函数中的现象。这将导致挂机过程中的数据丢失，故为避免数据丢失的现象出现，现已将发送函数挪动至子线程，并添加看门狗监视发送线程以保证测试过程中的数据安全；\n")
                       + tr("2.因为本程序涉及到了大量的数据处理（而且没有放在多线程中），所以在低性能PC高负载发送的情况下会出现界面卡顿异常的现象，在停止发送后会恢复正常；\n")
                       + tr("3.本程序在收发消息时会同时存在4个线程，故请尽量使用多核设备运行本程序；\n")
                       + tr("4.本程序采用信号量控制发送，故发送速率将与PC以及下位机的性能有直接关系；\n")
                       + tr("5.在PB-Box中本模块打开数据库时有概率出现打开失败的现象，疑似需要管理员权限。\n")
                       );

    //tAboutApp2_QFile.close();
}
//@FUNC:关于本程序的QT信息
void qHID_USB::on_action_QtVersion_triggered()
{
    QMessageBox::aboutQt(this,
                         tr("【Qt版本信息】"));
}
//@FUNC:手动获取更新信息
void qHID_USB::on_action_Update_triggered()
{
    QString tUpdateInfo_QStr = "软件名称：PB-Box HIDUSB模块<br>"
                               "软件名称：PB-Box HIDUSB模块<br>"
                               "软件版本：" + aVersion_QStr + "<br>"
                               "版本发布时间：" + aReleaseTime_QStr + "<br>"
                               "首次发布时间：2022年05月07日<br>"
                               "作者：Spectre<br>"
                               "邮箱：<a href='Spectre@petalmail.com'>Spectre@petalmail.com</a><br><br>"
                               "【应用声明】:<br>1.本软件大量使用了iconfont网站的图标（万分感谢各图标的作者！），如有侵权请联系删除；<br>"
                               "2.本软件的最终解释权归Spectre所有；<br>"
#if cLibModel == cEnable
                               "3.本软件已经上传蓝奏云，你可以通过如下连接获取到最新版本 ：<br><a href='https://wwc.lanzouy.com/b01jn009i'>https://wwc.lanzouy.com/b01jn009i</a> 【密码:7iak】<br>"
#else
                               "3.本软件已经上传蓝奏云，你可以通过如下连接获取到最新版本 ：<br><a href='https://wwc.lanzouy.com/b01jn006f'>https://wwc.lanzouy.com/b01jn006f</a> 【密码:4fts】<br>"
#endif
                               "4.本模块的源码已经上传至我的Gitee仓库，如果开源了你应该可以通过如下连接获取到源码，如果访问受限那么就还没开源：<br><a href='https://gitee.com/planb-council/pb_box-hid_usb_module'>https://gitee.com/planb-council/pb_box-hid_usb_module</a><br>"
                               "5.本软件不得运用于商业用途！";
    QMessageBox::about(this,
                       tr("【检查更新】"),
                       tUpdateInfo_QStr);
}
//@FUNC:手动添加收藏设备
void qHID_USB::on_action_AppendDev_triggered()
{
    aCareDev_QSqlRelationalTableModel->insertRow(aCareDev_QSqlRelationalTableModel->rowCount(),QModelIndex());

    QModelIndex tNewCurrent_QModelIndex = aCareDev_QSqlRelationalTableModel->index(aCareDev_QSqlRelationalTableModel->rowCount()-1,1);
    aCurCareDev_QItemSelectionModel->clearCurrentIndex();
    aCurCareDev_QItemSelectionModel->setCurrentIndex(tNewCurrent_QModelIndex,QItemSelectionModel::Select);
    ui->action_SaveCared->setEnabled(true);
}
//@FUNC:删除所选的收藏的设备
void qHID_USB::on_action_DeleteDev_triggered()
{
    if(QMessageBox::Ok == QMessageBox::warning(this,
                                               tr("警告"),
                                               tr("【提示】：删除操作不可逆，确认要删除？"),
                                               QMessageBox::Ok|QMessageBox::No,QMessageBox::Ok))      //@STUDY:这里设置OK|NO就行设置为Accepted就不行
    {
        aCareDev_QSqlRelationalTableModel->removeRow(aCurCareDev_QItemSelectionModel->currentIndex().row());
        aCareDev_QSqlRelationalTableModel->submitAll();
    }
}
//@FUNC:保存收藏页的修改
void qHID_USB::on_action_SaveCared_triggered()
{
    bool tResult_Bool = aCareDev_QSqlRelationalTableModel->submitAll();
    if(!tResult_Bool)
    {
        QMessageBox::warning(this,
                             tr("警告"),
                             tr("【错误-0】：保存修改失败，错误信息如下所示：\n")
                             + aCareDev_QSqlRelationalTableModel->lastError().text());
    }
    else
    {
        ui->action_SaveCared->setEnabled(false);
        ui->action_Uodo->setEnabled(false);
    }
}
//@FUNC:撤销未保存的修改
void qHID_USB::on_action_Uodo_triggered()
{
    aCareDev_QSqlRelationalTableModel->revertAll();
    ui->action_SaveCared->setEnabled(false);
    ui->action_Uodo->setEnabled(false);
}
